Validating Input
Check incoming data before using it, with a library like Zod or express-validator.
Syntax
schema.parse(req.body)Never trust client input. Validation makes sure the data has the right shape and types before you store it. If it fails, respond with 400 Bad Request and a helpful message.
Popular tools are Zod (schema-based) and express-validator (middleware-based). The example uses Zod to validate a request body.
Example
const { z } = require('zod');
const postSchema = z.object({
title: z.string().min(1).max(120),
published: z.boolean().optional(),
});
app.post('/posts', (req, res) => {
const result = postSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json({ errors: result.error.issues });
}
res.status(201).json(result.data);
});When to use it
- A registration endpoint validates that email is a valid address and password is at least 8 characters before inserting into the database.
- A team uses express-validator's check() chained calls to validate all fields of a product creation form and return field-level errors.
- A developer uses Joi schema validation in a middleware function to reject malformed request bodies before they reach the controller.
More examples
Manual field validation
Manually checks each field and collects error messages, returning a 400 with all errors at once.
app.post('/register', (req, res) => {
const { name, email, password } = req.body;
const errors = [];
if (!name) errors.push('name is required');
if (!/^\S+@\S+$/.test(email)) errors.push('valid email required');
if (!password || password.length < 8) errors.push('password min 8 chars');
if (errors.length) return res.status(400).json({ errors });
res.status(201).json({ registered: true });
});express-validator middleware
Uses express-validator's body() rules and validationResult() to validate and normalise email and password.
const { body, validationResult } = require('express-validator');
const validateUser = [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
];
app.post('/register', validateUser, (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() });
res.status(201).json({ ok: true });
});Joi schema validation middleware
Defines a Joi schema and wraps it in a middleware factory that validates req.body and returns all errors at once.
const Joi = require('joi');
const schema = Joi.object({
name: Joi.string().min(2).required(),
email: Joi.string().email().required(),
age: Joi.number().integer().min(0).optional(),
});
function validate(req, res, next) {
const { error } = schema.validate(req.body, { abortEarly: false });
if (error) return res.status(400).json({ errors: error.details.map(d => d.message) });
next();
}
app.post('/users', validate, (req, res) => res.status(201).json(req.body));
Discussion