REST API Request Validation
In this article we will look at how to validate POST requests to the REST API using Joi library. Joi lets you describe your data using a simple, intuitive, and readable language. We will also look at how to turn Joi errors into 422 Validation Error API responses.
Describe REST API Request Shema with Joi
We will be validating POST /v1/travels
REST API request in travels API project. You can find the project in this GitHub repository. For more in depth explanation, please watch the video below.
Let’s describe the schema of this request with Joi. In the middleware
folder let’s create requestSchemas.t
s file and put the following code.
import Joi from "joi";
export const createTravelSchema = Joi.object({
name: Joi.string().min(3).max(30).required(),
description: Joi.string(),
number_of_days: Joi.number().integer().greater(0).required(),
is_public: Joi.bool().default(true),
});
In the code above we describe incoming POST Request fields using Joi methods. Joi has a lot of methods, and you can find the ones for your specific use cases in Joi documentation.
Validate Joi Schema in the Middleware
Next in the middleware folder let’s create validateRequest.ts
middleware. We will use validateAsync
Joi method to validate the request body. If validateAsync
throws an error we will catch it and pass it to the ErrorHandler
.
import { NextFunction, Request, Response } from "express";
import { ObjectSchema } from "joi";
export default function validateRequest(schema: ObjectSchema) {
return async function validator(
req: Request,
res: Response,
next: NextFunction
) {
if (!req.body) {
next();
}
try {
await schema.validateAsync(req.body, { abortEarly: false });
} catch (error) {
next(error);
return;
}
next();
};
}
Add Request Validation Middleware to REST API Route
Finally, we will add validateRequest
middleware we created to create travel route in routes/v1/travels/index.ts
file.
import express, { Router } from "express";
import { listTravels, getTravel, createTravel } from "./controller";
import validateRequest from "../../../middleware/validateRequest";
import { createTravelSchema } from "../../../middleware/requestSchemas";
const travels: Router = express.Router();
travels.get("/", listTravels);
travels.get("/:id", getTravel);
travels.post("/", validateRequest(createTravelSchema), createTravel);
export default travels
Developing Back-End Apps with Node.js and Express
- Create server-side applications using the Node.js JavaScript run time.
- Use npm to manage Node.js packages in your Node.js application.
- Extend your Node.js applications with third-party packages and frameworks, including Express.
- Develop asynchronous callback functions and promises to complete asynchronous operations.
Return Joi Error as 422 REST API Validation Errors
After we catch Joi validation errors, we need to update ErrorHandler
code to return 422 Validation errors to the users. First we create ValidationError
type in types.d.ts
file.
type ErrorCode = "ERR_NF" | "ERR_REMOTE" | "NOT_IMPL" | "ERR_VALID";
type ValidationError = {
error: {
message: string;
code: ErrorCode;
errors: Array<{ message: string }>;
};
};
Then on line 15 of ErroHandler.ts
file we add the following if block.
if (Joi.isError(error)) {
const validationError: ValidationError = {
error: {
message: "Validation error",
code: "ERR_VALID",
errors: error.details.map((item) => ({
message: item.message,
})),
},
};
return res.status(422).json(validationError);
}
Conclusion
REST API request validation plays a critical role in building secure, reliable, and efficient web services. Joi library let’s you easily describe requests’ payloads and validate them. If request validation fails, Joi errors can be handled to return 422 validation errors to the API users.