Express Joi Middleware
raw JSON →express-joi-middleware is an Express.js middleware designed to integrate Hapi.js's Joi validation library seamlessly into Express applications. Currently at its first stable release, version 1.0.0, this package provides robust request body, query, parameters, and headers validation against user-defined Joi schemas. Its key differentiators include extensive customization options, such as the ability to supply a specific Joi instance (useful for managing Joi versions or custom extensions), fine-grained control over error response handling (either automatically sending a 400 Bad Request or `next`ing the Joi error for custom handling), and the choice to override the `req.body` or create a new `req.validated` key with the processed data. The project is new, so a specific release cadence has not yet been established, but it focuses on providing a flexible and configurable validation layer.
Common errors
error ReferenceError: Joi is not defined ↓
const Joi = require('joi'); at the top of the file where your Joi schemas are defined. error TypeError: app.use() requires a middleware function but got a Object ↓
expressJoiMiddleware(schemaObject, optionsObject) to return the middleware function, e.g., app.post('/path', expressJoiMiddleware(mySchema), (req, res) => ...);. error Error: Invalid IP address: 127.0.0.1 (Joi error) ↓
Warnings
gotcha The quickstart example in the README omits the explicit `require('joi')` statement, which is essential for defining Joi schemas. Without it, you will encounter runtime errors indicating `Joi is not defined`. ↓
gotcha By default (`wantResponse: false`), `express-joi-middleware` will `next` Joi validation errors to the next middleware. If you do not have a custom error-handling middleware set up to catch `err.isJoi` errors, these errors will propagate and potentially crash your application or result in generic 500 errors. ↓
gotcha As of version 1.0.0, this package is exclusively CommonJS. Attempting to use ESM `import` statements will result in a runtime error. ↓
Install
npm install express-joi-middleware yarn add express-joi-middleware pnpm add express-joi-middleware Imports
- expressJoiMiddleware wrong
import expressJoiMiddleware from 'express-joi-middleware';correctconst expressJoiMiddleware = require('express-joi-middleware'); - Joi wrong
import Joi from 'joi';correctconst Joi = require('joi');
Quickstart
const express = require('express');
const bodyParser = require('body-parser');
const Joi = require('joi'); // Crucial: Joi must be imported by the user
const expressJoiMiddleware = require('express-joi-middleware');
const app = express();
app.use(bodyParser.json());
const userSchema = {
body: {
id: Joi.string().guid({ version: 'uuidv4' }).required(),
name: Joi.string().min(3).max(30).required(),
email: Joi.string().email().required()
},
params: {
userId: Joi.string().guid({ version: 'uuidv4' }).required()
}
};
const options = {
wantResponse: true // Middleware sends 400 Bad Request automatically
};
// Example: Validating a POST request body
app.post('/users', expressJoiMiddleware(userSchema, options), (req, res) => {
// req.validated will contain the validated and transformed body/query/params
res.status(201).json({ message: 'User created successfully', data: req.validated });
});
// Example: Validating a GET request with path parameters
app.get('/users/:userId', expressJoiMiddleware(userSchema, options), (req, res) => {
res.json({ message: `Fetching user ${req.validated.userId}`, user: { id: req.validated.userId, name: 'Example User' } });
});
// Custom error handler for Joi errors if wantResponse is false or for other errors
app.use((err, req, res, next) => {
if (err.isJoi) {
console.error('Joi validation error:', err.details);
return res.status(400).json(err.details);
}
console.error('Internal server error:', err);
res.status(500).send('Internal Server Error');
});
app.listen(8080, () => {
console.log('Server listening on http://localhost:8080');
});