How to validate Node + Express requests with Joi middleware
Mattia Malonni
Posted on May 14, 2024
Validating inputs is one of the most important things you should do as a backend developer. No matter what language or framework you use, you must not trust user inputs, ever.
And when it comes to Node, there are a ton of libraries out there that enables you to achieve this result. One of them is, precisely, Joi.
In this article i would like to make use of my new middleware express-joi-validations to present a new way to validate user inputs in Express.
Suppose you have an endpoint for registering new user on /signup
route, you would have something like this:
import express from 'express';
const app = express();
app.post('/signup', (request, response) => {
const { username, email, password } = request.body;
});
If you now want to validate that username
, email
and password
meets your sing-up criteria, instead of using a bunch of if
statements, you can use Joi with the help of express-joi-validations middleware.
The output would be something like this:
import express from 'express';
import { Joi, validateBody } from 'express-joi-validations';
const app = express();
const userSignUp = Joi.object({
username: Joi.string().required().trim().alphanum().min(3).max(30),
email: Joi.string().required().trim().email(),
password: Joi.string().required().min(8),
});
app.post('/api/users', validateBody(userSignUp), (request, response) => {
const errors = request.validationErrors.body;
if (errors) {
response.status(400).json({ error: 'Invalid user inputs' })
}
const { username, email, password } = request.validationValues.body;
});
As you can see, express-joi-validations
exposes the method validateBody
that you can use to validate the payload of the body and the validated data will be in the request.validationValues.body
field.
If the input does not meet your criteria, the request.validationErrors.body
field will be populated with an array of Joi errors that you can use to be more specific on what went wrong.
In addition to the validateBody
method, you can use also the validateHeader
method to validate request headers:
import { Joi, validateHeaders } from 'express-joi-validations';
const userToken = Joi.object({
authorization: Joi.string().required().regex(/^Bearer [A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/=]*$/),
});
app.get('/api/secret', validateHeaders(userToken), (request, response) => {
// this area is restricted to registered users only
});
or the validateParams
and validateQuery
to validate url:
import { Joi, validateParams, validateQuery } from 'express-joi-validations';
// GET /posts/507f1f77bcf86cd799439011
const postId = Joi.object({
id: Joi.string().hex().length(24),
});
app.get('/posts/:id', validateParams(postId), (request, response) => {
const post = Post.findById(request.validationValues.params.id)
});
// GET /posts?page=2
const postQuery = Joi.object({
page: Joi.optional().number().integer().min(1).default(1),
});
app.get('/posts', validateQuery(postQuery), (request, response) => {
const posts = Post.findAll({ page: request.validationValues.query.page })
});
In addition to these helper methods, you can use the more generic validate
to combine multiple validations together:
import { Joi, validate } from 'express-joi-validations';
app.put('/posts/:id', validate({ headers: userToken, params: postId, body: postBody }), (request, response) => {
// Validation errors will be in request.validationErrors
// Validation values will be in request.validationValues
});
That's it for this article.
For a better customization of the middleware, please refer to the official GitHub repository: https://github.com/mattiamalonni/express-joi-validations
For any question feel free to ask in the comments section below or in DM.
Posted on May 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.