DEV Community

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

Posted on • Edited on

2

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.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay