Photo by King's Church International on Unsplash
Using Zod for Request Validation middleware in Express.js
Middleware police ๐๐๐
Ensuring that incoming data to an API is valid and well-formed is critical for maintaining application security and stability. Here's a guide on how to use Zod, a TypeScript-first schema declaration and validation library, to validate request data in an Express.js application. This note will help me quickly recall the implementation details.
Why Validate Request Data?
Security: Prevents potential security vulnerabilities.
Data Integrity: Ensures data conforms to expected formats and types.
Error Handling: Provides clear feedback for debugging and user experience.
Using Zod
Zod simplifies schema validation with a clean API and native TypeScript support, making it ideal for type-safe projects.
Middleware Implementation
This middleware validates request data against a Zod schema:
import { Request, Response, NextFunction } from 'express';
import { AnyZodObject } from 'zod';
/**
* Middleware to validate request data against a provided Zod schema.
*
* @param schema The Zod schema to validate the request data against.
* @returns A middleware function that parses the request body and either forwards control to the next middleware or passes an error to the error handling middleware.
*/
const validateRequest = (schema: AnyZodObject) => {
return async (req: Request, res: Response, next: NextFunction) => {
try {
// Validate the request body against the schema
await schema.parseAsync({ body: req.body });
next(); // Proceed if successful
} catch (error) {
// Pass validation errors to the error handling middleware
next(error);
}
};
};
How It Works
Schema Definition: Define a Zod schema for the request body.
Middleware Function:
validateRequest
takes the schema and returns an async middleware function.Validation:
schema.parseAsync
validatesreq.body
against the schema.Error Handling: Calls
next()
to proceed if valid, otherwise passes the error to the next middleware.
Example Usage
Practical example of using the middleware in an Express.js route:
import express from 'express';
import { z } from 'zod';
import validateRequest from './validateRequest';
const app = express();
app.use(express.json());
//example of schema
const userSchema = z.object({
body:z.object({
name: z.string().min(1),
email: z.string().email(),
age: z.number().int().positive(),
})
});
//before going to the controller its validate frist
app.post('/users', validateRequest(userSchema), (req, res) => {
res.send('User data is valid!');
});
// Error handling middleware
app.use((err, req, res, next) => {
if (err instanceof z.ZodError) {
res.status(400).json({
message: 'Validation failed',
issues: err.errors,
});
} else {
res.status(500).json({ message: 'Internal Server Error' });
}
});
app.listen(3000, () => console.log('Server running on port 3000'));
Conclusion
Using Zod for request validation in Express.js enhances security, ensures data integrity, and improves error handling. This approach keeps my APIs robust and my codebase maintainable, leveraging the power of TypeScript for type-safe validation.