Як перевірити дані запиту в Express.js?
Валідація запитів в Express.js
Ніколи не довіряйте введенню з клієнта. Валідація та санітизація даних запиту (тіло, параметри, запит) перед їх обробкою є критично важливою практикою безпеки та надійності.
Варіант 1: Zod (TypeScript-орієнтований)
bash
npm install zodjs
const { z } = require('zod');
// Визначення схеми
const createUserSchema = z.object({
body: z.object({
name: z.string().min(2).max(50),
email: z.string().email(),
age: z.number().int().min(18).max(120).optional(),
role: z.enum(['user', 'admin']).default('user'),
})
});
// Повторно використовуваний middleware для валідації
function validate(schema) {
return (req, res, next) => {
try {
schema.parse({
body: req.body,
query: req.query,
params: req.params,
});
next();
} catch (err) {
const errors = err.errors.map(e => ({
field: e.path.join('.'),
message: e.message
}));
res.status(400).json({ error: 'Валідація не пройшла', details: errors });
}
};
}
// Використання в маршрутах
app.post('/users',
validate(createUserSchema),
asyncHandler(async (req, res) => {
const user = await usersService.create(req.body);
res.status(201).json({ data: user });
})
);Варіант 2: express-validator
bash
npm install express-validatorjs
const { body, param, query, validationResult } = require('express-validator');
// Правила валідації
const createUserRules = [
body('name').trim().isLength({ min: 2, max: 50 }).withMessage('Ім\'я повинно бути 2-50 символів'),
body('email').isEmail().normalizeEmail().withMessage('Невірний email'),
body('age').optional().isInt({ min: 18 }).withMessage('Повинно бути 18+'),
body('password').isStrongPassword().withMessage('Пароль занадто слабкий'),
];
// Збір та повернення помилок
function checkValidation(req, res, next) {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
error: 'Валідація не пройшла',
details: errors.array()
});
}
next();
}
app.post('/users', createUserRules, checkValidation, createUser);Валідація параметрів URL та рядків запиту
js
const getUserRules = [
param('id').isInt({ min: 1 }).withMessage('ID повинен бути позитивним цілим числом'),
];
const listUsersRules = [
query('page').optional().isInt({ min: 1 }).default(1),
query('limit').optional().isInt({ min: 1, max: 100 }).default(10),
query('sort').optional().isIn(['name', 'email', 'createdAt']),
];
app.get('/users', listUsersRules, checkValidation, getUsers);
app.get('/users/:id', getUserRules, checkValidation, getUser);Варіант 3: Joi
bash
npm install joijs
const Joi = require('joi');
const createUserSchema = Joi.object({
name: Joi.string().min(2).max(50).required(),
email: Joi.string().email().required(),
password: Joi.string().min(8).required(),
role: Joi.string().valid('user', 'admin').default('user'),
});
function validate(schema) {
return (req, res, next) => {
const { error, value } = schema.validate(req.body, { abortEarly: false });
if (error) {
const details = error.details.map(d => d.message);
return res.status(400).json({ error: 'Валідація не пройшла', details });
}
req.body = value; // використовувати санітизоване/типізоване значення
next();
};
}Порівняння
| Бібліотека | Стиль | TypeScript | Розмір пакету |
|---|---|---|---|
| Zod | Схема-орієнтований, TypeScript-орієнтований | Відмінно | Середній |
| express-validator | Ланцюговий API, Express-орієнтований | Добре | Малий |
| Joi | Схема-орієнтований, Hapi-орієнтований | Добре | Середній |
Резюме
Завжди валідуйте: тіло, параметри та запит перед обробкою. Використовуйте патерн middleware для чистої, повторно використовуваної валідації. Zod рекомендується для проектів на TypeScript для забезпечення типобезпеки. Поверніть 400 Bad Request з деталями, коли валідація не пройшла.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.