Do you think validate types in JavaScript is boring?
Have you heard about Yup? It's an amazing JavaScript lib to validate schemas!
Let's imagine:
We have a list products
endpoint, which takes the page number
and limit
as arguments from querystring
//productApi.js
const { Router } = require('express');
const productController = require('./controller');
const router = new Router();
module.exports = app => app.use('/products', router);
router.get('/', (req, res, next) => {
const { page, limit } = req.query;
if (isNaN(page) || isNaN(limit)) return res.status(400).end();
productController.list({ page: Number(page), limit: Number(limit) })
.then(products => res.json(products))
.catch(error => res.status(400).json({ error }));
}
The problem is: page
and limit
can be undefined
and... anything else
... it's javascript baby.
A very efficient way is to create a middleware to validate your params using Yup.
//validate.js
const yup = require('yup');
module.exports = ({ shape, path = 'query' }) => async (req, res, next) => {
const schema = yup.object().shape(shape);
try {
const validData = await schema.validate(req[path]);
req.validData = validData;
return next();
} catch (error) {
return res.status(400).json({ error });
}
};
After then, use on route
//productApi.js
const { Router } = require('express');
const yup = require('yup');
const validate = require('./validate');
const productController = require('./controller');
const router = new Router();
module.exports = app => app.use('/products', router);
router.get(
'/',
validate({
shape: {
page: yup.number().default(0),
limit: yup.number().default(15),
}
}),
(req, res, next) => {
productController
.list(req.validData)
.then(products => res.json(products))
.catch(error => res.status(400).json({ error }));
},
);
Of course you can create complex schemas with Yup. It works as you need.
I hope it helps someone!
Top comments (10)
Awesome post João, thanks!
I've used Joi but it's pretty sluggish depending on the validation rules you need to implement. I've stumbled across github.com/icebob/fastest-validator, which is my go-to Javascript "spec/schema" definition package at the moment.
Glad to read this!
I never heard about
fastest-validator
before. Thanks for share! Seems to be really fast 😱how are you using this with express routes? middleware? mind sharing how your middleware looks
You need to make a manual middleware passing the schema, just as a custom middleware for joi/yup/express-validator, etc.
Other middlewares (like celebrate) might add extra features like distinct body, query and params validation.
That implementation using on routes was really cool! I have seen people using Joi, though, never heard of Yup. Gonna check it out later.
Yup's api/style was inspired by Joi!
Awesome tips bro!
Thanks, it helps me a lot.
nice post! how do you validate query params and body at the same time using your middleware
You'd need to create a custom middleware, validate, sanitize and pass everything over to the route, or you can search for middlewares in npm.