Cómo hacer que la validación de entrada sea simple y limpia en su aplicación Express.js

Este tutorial requiere conocimientos previos sobre el uso del marco expressjs

¿Por qué necesitamos la validación del lado del servidor?

  • Su validación del lado del cliente no es suficiente y puede ser subvertida
  • Más propenso a los ataques Man in middle, y el servidor nunca debería confiar en el lado del cliente
  • Un usuario puede desactivar la validación de JavaScript del lado del cliente y manipular los datos

Si ha estado creando aplicaciones web utilizando un marco Express o cualquier otro marco Node.js, la validación juega un papel crucial en cualquier aplicación web que requiera que valide la solicitud bodyparamquery.

Escribir su propia función de middleware puede resultar engorroso si

  • desea moverse rápido mientras mantiene la calidad del código o
  • desea evitar usar o en su función de controlador principal donde define la lógica de negociosif (req.body.head)if (req.params.isCool)

En este tutorial, aprenderá cómo validar la entrada en una aplicación Express.js utilizando un módulo popular y de código abierto llamado express-validator.

Introducción a express-validator

La definición en Github dice:

express-validator es un conjunto de middlewares express.js que envuelve las funciones de validación y desinfección de validator.js.

El módulo implementa cinco API importantes:

  • Ver API
  • API de filtro
  • API de cadena de desinfección
  • API de cadena de validación
  • API de resultados de validación

Echemos un vistazo a un usuario básico routesin ningún módulo de validación para crear un usuario:/route/user.js

/** * @api {post} /api/user Create user * @apiName Create new user * @apiPermission admin * @apiGroup User * * @apiParam {String} [userName] username * @apiParam {String} [email] Email * @apiParam {String} [phone] Phone number * @apiParam {String} [status] Status * * @apiSuccess (200) {Object} mixed `User` object */ router.post('/', userController.createUser)

Ahora en controlador de usuario /controllers/user.js

const User = require('./models/user') exports.createUser = (req, res, next) => { /** Here you need to validate user input. Let's say only Name and email are required field */ const { userName, email, phone, status } = req.body if (userName && email && isValidEmail(email)) { // isValidEmail is some custom email function to validate email which you might need write on your own or use npm module User.create({ userName, email, phone, status, }) .then(user => res.json(user)) .catch(next) } }

El código anterior es solo un ejemplo básico de validación de campos por su cuenta.

Puede manejar algunas validaciones en su modelo de usuario usando Mongoose. Para las mejores prácticas, queremos asegurarnos de que la validación ocurra antes que la lógica empresarial.

express-validator se encargará de todas estas validaciones y también de la desinfección de las entradas.

Instalación

npm install --save express-validator

Incluya el módulo en su server.jsarchivo principal :

const express = require('express') const bodyParser = require('body-parser') const expressValidator = require('express-validator') const app = express() const router = express.Router() app.use(bodyParser.json()) app.use(expressValidator()) app.use('/api', router)

Ahora usando express-validator, /routes/user.jsserá así:

router.post( '/', userController.validate('createUser'), userController.createUser, )

Aquí userController.validatehay una función de middleware que se explica a continuación. Acepta el methodnombre para el que se utilizará la validación.

Creemos una función de middleware validate()en nuestro /controllers/user.js:

const { body } = require('express-validator/check') exports.validate = (method) => { switch (method) { case 'createUser': { return [ body('userName', 'userName doesn't exists').exists(), body('email', 'Invalid email').exists().isEmail(), body('phone').optional().isInt(), body('status').optional().isIn(['enabled', 'disabled']) ] } } }

Consulte este artículo para obtener más información sobre la definición de funciones y su uso.

La bodyfunción solo validará req.bodyy toma dos argumentos. Primero es el property name. En segundo lugar, está su costumbre messageque se mostrará si falla la validación. Si no proporciona un mensaje personalizado, se utilizará el mensaje predeterminado.

Como puede ver, para un requiredcampo estamos usando el .exists()método. Estamos usando .optional()para un optionalcampo. De manera similar isEmail()isInt()se usa para validar emaily integer.

Si desea que un campo de entrada incluya solo ciertos valores, puede usar .isIn([]). Esto toma un arrayvalor de, y si recibe valores distintos a los anteriores, se generará un error.

Por ejemplo, el campo de estado en el fragmento de código anterior solo puede tener un valor enabledo disabled. Si proporciona cualquier valor que no sea ese, se producirá un error.

En /controllers/user.js, escriba una createUserfunción en la que pueda escribir lógica empresarial. Se llamará despuésvalidate()con el resultado de las validaciones.

const { validationResult } = require('express-validator/check'); exports.createUser = async (req, res, next) => { try { const errors = validationResult(req); // Finds the validation errors in this request and wraps them in an object with handy functions if (!errors.isEmpty()) { res.status(422).json({ errors: errors.array() }); return; } const { userName, email, phone, status } = req.body const user = await User.create({ userName, email, phone, status, }) res.json(user) } catch(err) { return next(err) } }

Si se pregunta qué es validationResult (req)?

Esta función encuentra los errores de validación en esta solicitud y los envuelve en un objeto con funciones útiles

Ahora, siempre que la solicitud incluya parámetros de cuerpo no válidos o userNamefalte un campo req.body, su servidor responderá así:

{ "errors": [{ "location": "body", "msg": "userName is required", "param": "userName" }] }

Entonces, si userNameo emailno logró satisfacer la validación, cada error devuelto por el .array()método tiene el siguiente formato por defecto:

{ "msg": "The error message", "param": "param name", "value": "param value", // Location of the param that generated this error. // It's either body, query, params, cookies or headers. "location": "body", // nestedErrors only exist when using the oneOf function "nestedErrors": [{ ... }] }

Como puede ver, este módulo realmente nos ayuda a encargarnos de la mayoría de las validaciones por sí solo. También mantiene la calidad del código y se centra principalmente en la lógica empresarial.

Esta fue la introducción a la validación de entrada usando el módulo express-validator y vea cómo validar una matriz del artículo y hacer su propia validación personalizada en la Parte 2 de esta serie.

He hecho todo lo posible y espero haber cubierto lo suficiente para explicarlo en detalle para que pueda comenzar.

Si tiene algún problema, no dude en ponerse en contacto o comentar a continuación.

Me gustaría ayudar :)

Sigue a Shailesh Shekhawat para recibir notificaciones cada vez que publique una nueva publicación.

¡No dudes en aplaudir si consideras que es una lectura que vale la pena!

Publicado originalmente en 101node.io el 2 de septiembre de 2018.