Request Validator (Zod)
The Request Validator component provides a standardized way to validate request data (body, query parameters, and route parameters) in ServerCN using Zod schemas.
It automatically:
- Validates request body, query, and params using Zod schemas
- Returns detailed validation error messages
- Integrates seamlessly with ServerCN error handling
- Provides type-safe request data after validation
This middleware is designed for type-safe, schema-based validation in REST APIs.
Installation Guide
This component requires additional ServerCN components.
👉 Note: You do not need to install any servercn dependencies manually. Installing this component will automatically install all required servercn dependencies. Manual installation is optional if you prefer to manage dependencies yourself.
1. Install ServerCN dependencies(Optional)
- HTTP Status Codes:
npx servercn add http-status-codesDocumentation: HTTP Status Codes
- API Error Handler:
npx servercn add error-handlerDocumentation: API Error Handler
2. Install this component
npx servercn add request-validator⚠️ If these dependencies are not installed, the component will not function correctly.
How Validation Works
The Request Validator middleware follows this sequence:
- Schema Definition: Define Zod schemas for body, query, or params
- Middleware Application: Apply
validateRequestmiddleware to routes - Validation: Middleware validates incoming request data against schemas
- Error Handling: If validation fails, returns detailed error messages
- Type Safety: Validated data is typed and attached to the request object
This ensures type-safe request handling with clear validation error messages.
Middleware Implementation
1. MVC Structure
src/middlewares/validate-request.ts
import { Request, Response, NextFunction } from "express";
import z, { ZodError, type ZodObject } from "zod";
import { ApiError } from "../utils/api-error";
export const validateRequest = (schema: ZodObject<any>) => {
return (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse(req.body);
next();
} catch (error) {
if (!(error instanceof ZodError)) {
return next(error);
}
throw ApiError.badRequest(
"Invalid request data",
z.flattenError(error).fieldErrors || z.flattenError(error)
);
}
};
};2. Feature Structure
src/shared/middlewares/validate-request.ts
import { Request, Response, NextFunction } from "express";
import z, { ZodError, type ZodObject } from "zod";
import { ApiError } from "../utils/api-error";
export const validateRequest = (schema: ZodObject<any>) => {
return (req: Request, res: Response, next: NextFunction) => {
try {
schema.parse(req.body);
next();
} catch (error) {
if (!(error instanceof ZodError)) {
return next(error);
}
throw ApiError.badRequest(
"Invalid request data",
z.flattenError(error).fieldErrors || z.flattenError(error)
);
}
};
};Schema Definition
Create validation schemas using Zod.
1. MVC Structure
src/validations/user.validation.ts
import z from "zod";
export const createUserSchema = z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
age: z.number().int().min(18).max(100).optional()
});2. Feature Structure
src/modules/user/user.validation.ts
import z from "zod";
export const createUserSchema = z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
age: z.number().int().min(18).max(100).optional()
});Usage Example
Apply the validateRequest middleware to your routes with the appropriate schema.
1. MVC Structure
src/routes/user.routes.ts
import { Router } from "express";
import { validateRequest } from "../middlewares/validate-request";
import { createUserSchema } from "./user.validation";
const router = Router();
router.post("/", validateRequest(createUserSchema), (req, res) => {
return res.status(201).json({ success: true, data: req.body });
});
export default router;2. Feature Structure
src/modules/user/user.routes.ts
import { Router } from "express";
import { validateRequest } from "../../shared/middlewares/validate-request";
import { createUserSchema } from "./user.validation";
const router = Router();
router.post("/", validateRequest(createUserSchema), (req, res) => {
return res.status(201).json({ success: true, data: req.body });
});
export default router;Validation Error Responses
When validation fails, the handler returns a standardized 400 Bad Request response with detailed error information:
{
"success": false,
"message": "Invalid request data",
"statusCode": 400,
"errors": {
"email": ["Invalid email address"],
"password": ["Password must be at least 8 characters"],
"age": ["You must be 18 or older to create an account"]
}
}(The exact structure depends on your ApiError implementation.)
Best Practices
- Separate Schemas: Create separate validation files for each resource/module
- Reusable Schemas: Extract common validation patterns into shared schemas
- Clear Error Messages: Provide descriptive error messages in your Zod schemas
- Type Safety: Use Zod's type inference for TypeScript type safety
- Transform Data: Use Zod's transform methods to convert query strings to numbers, dates, etc.
- Validate Early: Apply validation middleware before business logic
- Consistent Structure: Keep validation schemas organized and consistent across your application