DEV Community

Cover image for How to validate Node + Express requests with Joi middleware
Mattia Malonni
Mattia Malonni

Posted on • Edited on

How to validate Node + Express requests with Joi middleware

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;
});
Enter fullscreen mode Exit fullscreen mode

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;
});
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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 })
});
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)