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.

  • HTTP Status Codes:
npx servercn add http-status-codes

Documentation: HTTP Status Codes

  • API Error Handler:
npx servercn add error-handler

Documentation: API Error Handler

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:

  1. Schema Definition: Define Zod schemas for body, query, or params
  2. Middleware Application: Apply validateRequest middleware to routes
  3. Validation: Middleware validates incoming request data against schemas
  4. Error Handling: If validation fails, returns detailed error messages
  5. 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

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)
      );
    }
  };
};
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.

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()
});
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.

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;
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

File & Folder Structure

Select a file to view its contents

Installation

npx servercn add request-validator