My Express API expone un punto final POST para crear un usuario, y necesito validar los datos antes de insertarlos en la base de datos, tengo dos métodos en mente:
Método 1: Incluya la validación del modelo en el controlador y repítalo para cada modelo:
// controllers/users.js exports.createUser = async function (req, res) { const { username, email, password } = req.body; /* validation logic */ /* interact with db */Método 2: Mueva la lógica de validación a un middleware dedicado:
// middleware/validators.js exports.validateArticle = function (req, res, next) {}; exports.validateComment = function (req, res, next) {}; exports.validateUser = function (req, res, next) { const { username, email, password } = req.body; /* validation logic */ if (!isValid) { return res.statusCode(400); } next(); }; // routes/users.js const { validateUser } = require('../middlewares/validators'); router.route('/').post(validateUser, createUser);mi preocupación con el método 2 es que la lógica para un método de punto final estaría dispersa entre muchos archivos, pero ¿cuál de estos métodos sigue las mejores prácticas?
Puedo sugerirle que use un middleware express-validator listo para usar y que lo configure así:
// src/validation/validation.js const { validationResult } = require('express-validator'); const validate = (schemas) => { return async (req, res, next) => { await Promise.all(schemas.map((schema) => schema.run(req))); const result = validationResult(req); if (result.isEmpty()) { return next(); } const errors = result.array(); return res.send({ message: 'Validation error', errors: errors, }) }; } module.exports = { validate }esta es una función que puede llamar como middleware en su enrutador, luego un archivo con reglas de validación.
// src/validation/validationSchemas.js const { body } = require('express-validator'); const addUserSchema = [ body('username').isLength({ min: 4, max: 16 }).withMessage('Username must be at least 4 and no more than 16 characters'), body('email').isEmail().withMessage('Incorrect email') ]; module.exports = { addUserSchema }y en tu enrutador:
const { validate } = require('../validation/validation'); const { registrationSchema, loginSchema } = require('../validation/validationSchemas'); router.post('/registration', validate(registrationSchema), userController.registration);El problema es de escala. Si hay muchas rutas diferentes en un controlador, o si solo tiene varios controladores, puede ser difícil mantener las cosas limpias y fáciles de entender. El controlador no debería tener mucho más de lo necesario para mostrar cómo se enrutan y devuelven las solicitudes entrantes. Todo lo demás que no sea trivial debe pasarse a un servicio de middleware. Por lo tanto, la segunda opción tiende a funcionar mejor si quieres espacio para crecer.
Además, al juntar toda su lógica de validación, puede reutilizar fácilmente el código cuando corresponda.
La opción 1 puede funcionar si esto es muy estático y no tiene expectativas de que se agreguen nuevas rutas o controladores.