Валидация перед сохранением — процесс проверки данных до их записи в базу данных, файл, очередь сообщений или внешний API. Основная цель — гарантировать корректность, безопасность и согласованность информации.
Библиотека Validator.js предоставляет набор готовых функций для проверки строковых значений: email, URL, UUID, IP-адресов, чисел, дат, JSON, банковских карт и множества других форматов.
Типичный поток обработки данных:
Получение данных -> Очистка -> Валидация -> Сохранение
Без предварительной проверки возможны:
npm install validator
CommonJS:
const validator = require('validator');
ES Modules:
import validator from 'validator';
Перед сохранением данные обычно проверяются на наличие значения.
import validator from 'validator';
const name = '';
if (validator.isEmpty(name)) {
console.log('Имя обязательно');
}
const value = ' ';
if (validator.isEmpty(value.trim())) {
console.log('Строка пустая');
}
function validateRequired(data) {
const errors = {};
if (validator.isEmpty(data.name.trim())) {
errors.name = 'Введите имя';
}
if (validator.isEmpty(data.email.trim())) {
errors.email = 'Введите email';
}
return errors;
}
Email — одно из самых распространённых полей.
const email = 'admin@example.com';
if (validator.isEmail(email)) {
console.log('Email корректен');
}
validator.isEmail(email, {
allow_utf8_local_part: false,
require_tld: true
});
function validateUser(user) {
const errors = {};
if (!validator.isEmail(user.email)) {
errors.email = 'Некорректный email';
}
return errors;
}
Validator.js не содержит отдельного метода проверки сложности пароля, но предоставляет инструменты для построения правил.
const password = 'qwerty';
if (!validator.isLength(password, { min: 8 })) {
console.log('Минимум 8 символов');
}
const strongPassword =
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/;
if (!strongPassword.test(password)) {
console.log('Слабый пароль');
}
function validatePassword(password) {
const errors = [];
if (!validator.isLength(password, { min: 8 })) {
errors.push('Минимум 8 символов');
}
if (!/[A-Z]/.test(password)) {
errors.push('Добавьте заглавную букву');
}
if (!/\d/.test(password)) {
errors.push('Добавьте цифру');
}
return errors;
}
validator.isInt('100');
validator.isInt('25', {
min: 18,
max: 60
});
validator.isFloat('10.55');
function validatePrice(price) {
return validator.isFloat(price.toString(), {
min: 0
});
}
validator.isDate('2025-05-10');
validator.isISO8601('2025-05-10T12:00:00Z');
function validateBirthDate(date) {
if (!validator.isDate(date)) {
return false;
}
const birthday = new Date(date);
const now = new Date();
return birthday < now;
}
validator.isURL('https://example.com');
validator.isURL('https://example.com', {
protocols: ['https'],
require_protocol: true
});
function validateWebsite(url) {
return validator.isURL(url, {
require_protocol: true
});
}
UUID часто используется как идентификатор записей.
validator.isUUID(
'550e8400-e29b-41d4-a716-446655440000'
);
validator.isUUID(uuid, 4);
validator.isJSON('{"name":"Alex"}');
function validateConfig(config) {
if (!validator.isJSON(config)) {
throw new Error('Некорректный JSON');
}
return JSON.parse(config);
}
validator.isIP('192.168.1.1', 4);
validator.isIP('2001:db8::1', 6);
validator.isLength(username, {
min: 3,
max: 20
});
function validateDescription(text) {
return validator.isLength(text, {
min: 10,
max: 500
});
}
Validator.js умеет не только проверять, но и очищать данные.
const value = validator.trim(' hello ');
console.log(value);
Результат:
hello
const text = '<script>alert(1)</script>';
const safe = validator.escape(text);
console.log(safe);
Результат:
<script>alert(1)</script>
const email =
validator.normalizeEmail('Admin@Example.COM');
console.log(email);
Результат:
admin@example.com
validator.whitelist('phone: +7(777)-123', '0-9');
Результат:
7777123
import validator from 'validator';
function validateUser(user) {
const errors = {};
if (
validator.isEmpty(user.name.trim())
) {
errors.name = 'Имя обязательно';
}
if (
!validator.isLength(user.name, {
min: 2,
max: 50
})
) {
errors.name =
'Имя должно быть от 2 до 50 символов';
}
if (
!validator.isEmail(user.email)
) {
errors.email =
'Некорректный email';
}
if (
!validator.isLength(user.password, {
min: 8
})
) {
errors.password =
'Минимум 8 символов';
}
if (
!validator.isInt(user.age.toString(), {
min: 18
})
) {
errors.age =
'Возраст должен быть больше 18';
}
return {
valid: Object.keys(errors).length === 0,
errors
};
}
import validator from 'validator';
const userSchema = new mongoose.Schema({
email: {
type: String,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Некорректный email');
}
}
}
});
async function createUser(data) {
if (!validator.isEmail(data.email)) {
throw new Error('Некорректный email');
}
if (!validator.isLength(data.name, {
min: 2
})) {
throw new Error('Слишком короткое имя');
}
await db.query(
'INS ERT INTO users(name, email) VALUES($1, $2)',
[data.name, data.email]
);
}
import validator from 'validator';
function validateUser(req, res, next) {
const { email, password } = req.body;
if (!validator.isEmail(email)) {
return res.status(400).json({
error: 'Некорректный email'
});
}
if (!validator.isLength(password, {
min: 8
})) {
return res.status(400).json({
error: 'Слабый пароль'
});
}
next();
}
Санитизация — очистка потенциально опасных данных.
function sanitizeUser(user) {
return {
name: validator.escape(
validator.trim(user.name)
),
email: validator.normalizeEmail(
user.email
),
about: validator.escape(
user.about
)
};
}
Validator.js работает со строками, поэтому элементы массива обычно проверяются по отдельности.
function validateEmails(emails) {
return emails.every(email =>
validator.isEmail(email)
);
}
function validateIds(ids) {
return ids.every(id =>
validator.isUUID(id)
);
}
Некоторые проверки требуют обращения к базе данных.
async function validateUniqueEmail(email) {
if (!validator.isEmail(email)) {
return false;
}
const user = await User.findOne({ email });
return !user;
}
function validateOrder(order) {
const errors = [];
if (!validator.isUUID(order.userId)) {
errors.push('Некорректный ID пользователя');
}
if (!Array.isArray(order.items)) {
errors.push('Список товаров обязателен');
}
if (order.items.length === 0) {
errors.push('Добавьте товары');
}
if (!validator.isFloat(
order.total.toString(),
{ min: 0 }
)) {
errors.push('Некорректная сумма');
}
return errors;
}
const rules = {
username: val ue =>
validator.isLength(value, {
min: 3,
max: 20
}),
email: value =>
validator.isEmail(value),
age: value =>
validator.isInt(value.toString(), {
min: 18
})
};
function validate(data, rules) {
const errors = {};
for (const field in rules) {
const valid =
rules[field](data[field]);
if (!valid) {
errors[field] =
`Ошибка поля ${field}`;
}
}
return errors;
}
function validationError(errors) {
return {
status: 'error',
errors
};
}
const errors = validateUser(user);
if (Object.keys(errors).length) {
return res.status(400).json(
validationError(errors)
);
}
Многие методы Validator.js ожидают строку.
Неправильно:
validator.isEmail(undefined);
Правильно:
validator.isEmail(String(value || ''));
Неправильно:
validator.isEmail(' admin@example.com ');
Правильно:
validator.isEmail(
validator.trim(email)
);
Проверка на клиенте удобна для UX, но серверная валидация обязательна.
Нельзя полагаться только на браузер:
<input type="email">
Проверка должна повторяться на сервере:
validator.isEmail(req.body.email)
Хорошая практика:
controllers/
services/
validators/
models/
validators/
userValidator.js
orderValidator.js
productValidator.js
import validator from 'validator';
export function validateUser(data) {
const errors = {};
if (!validator.isEmail(data.email)) {
errors.email = 'Некорректный email';
}
return errors;
}
import { validateUser } from './validators/userValidator.js';
app.post('/users', async (req, res) => {
const errors =
validateUser(req.body);
if (Object.keys(errors).length) {
return res.status(400).json({
errors
});
}
await User.create(req.body);
res.json({
success: true
});
});
Validator.js работает быстро, но при больших объёмах данных важно:
const validUsers = users.filter(user =>
validator.isEmail(user.email)
);
app.post('/api/products', (req, res) => {
const { title, price } = req.body;
if (
!validator.isLength(title, {
min: 3
})
) {
return res.status(400).json({
error: 'Короткое название'
});
}
if (
!validator.isFloat(price.toString(), {
min: 0
})
) {
return res.status(400).json({
error: 'Некорректная цена'
});
}
res.json({
success: true
});
});
function validateFilename(name) {
return validator.matches(
name,
/^[a-zA-Z0-9_\-.]+$/
);
}
validator.isMobilePhone(
'+77011234567',
'kk-KZ'
);
validator.isMobilePhone(
phone,
['ru-RU', 'kk-KZ']
);
validator.isSlug('my-awesome-post');
validator.isCreditCard('4111111111111111');
validator.isHash(hash, 'md5');
validator.isHash(hash, 'sha256');
validator.isBase64(fileContent);
function createError(field, message) {
return {
field,
message
};
}
if (!validator.isEmail(email)) {
errors.push(
createError(
'email',
'Некорректный email'
)
);
}
email: {
type: DataTypes.STRING,
validate: {
isEmail: true
}
}
@Column()
email;
if (!validator.isEmail(user.email)) {
throw new Error('Некорректный email');
}
Надёжная система обычно включает несколько уровней:
ALT ER TABLE users
ADD CONSTRAINT check_age
CHECK (age >= 18);
import validator from 'validator';
async function registerUser(data) {
const errors = {};
const email =
validator.normalizeEmail(
data.email
);
const name =
validator.escape(
validator.trim(data.name)
);
if (!validator.isEmail(email)) {
errors.email =
'Некорректный email';
}
if (!validator.isLength(name, {
min: 2,
max: 50
})) {
errors.name =
'Некорректное имя';
}
if (!validator.isLength(
data.password,
{ min: 8 }
)) {
errors.password =
'Слабый пароль';
}
const exists =
await User.findOne({ email });
if (exists) {
errors.email =
'Email уже используется';
}
if (Object.keys(errors).length) {
throw errors;
}
return await User.create({
email,
name,
password: data.password
});
}