Skip to main content

Overview

The validator middleware provides declarative request validation with built-in rules for common validation needs. It validates query parameters, form fields, headers, and path parameters. Use it when you need:
  • Input validation
  • Form validation
  • API parameter validation
  • Custom validation rules

Installation

import "github.com/go-mizu/mizu/middlewares/validator"

Quick Start

app := mizu.New()

app.Post("/users", createUser, validator.New(
    validator.Field("email", "required", "email"),
    validator.Field("name", "required", "min:2", "max:50"),
))

Built-in Rules

RuleDescriptionExample
requiredField must not be empty"required"
min:nMinimum string length"min:3"
max:nMaximum string length"max:100"
emailValid email format"email"
numericNumeric value"numeric"
integerInteger value"integer"
alphaLetters only"alpha"
alphanumLetters and numbers only"alphanum"
in:a,b,cMust be one of values"in:pending,active,done"
urlValid URL"url"
uuidValid UUID format"uuid"

Examples

Basic Validation

app.Post("/register", registerHandler, validator.New(
    validator.Field("username", "required", "alphanum", "min:3", "max:20"),
    validator.Field("email", "required", "email"),
    validator.Field("password", "required", "min:8"),
))

Optional Fields

app.Put("/profile", updateProfile, validator.New(
    validator.OptionalField("bio", "max:500"),
    validator.OptionalField("website", "url"),
))

Enum Validation

app.Post("/tasks", createTask, validator.New(
    validator.Field("title", "required", "min:1", "max:200"),
    validator.Field("status", "required", "in:pending,in_progress,done"),
    validator.Field("priority", "required", "in:low,medium,high"),
))

JSON Body Validation

app.Post("/api/users", createUser, validator.JSON(map[string][]string{
    "email":    {"required", "email"},
    "name":     {"required", "min:2"},
    "age":      {"numeric"},
}))

Custom Error Handler

app.Use(validator.WithOptions(validator.Options{
    Rules: []validator.Rule{
        validator.Field("email", "required", "email"),
    },
    ErrorHandler: func(c *mizu.Ctx, errors validator.ValidationErrors) error {
        return c.JSON(422, map[string]any{
            "message": "Validation failed",
            "errors":  errors,
        })
    },
}))

Custom Error Messages

app.Post("/contact", contactHandler, validator.New(
    validator.Rule{
        Field:   "email",
        Rules:   []string{"required", "email"},
        Message: "Please provide a valid email address",
    },
    validator.Rule{
        Field:   "message",
        Rules:   []string{"required", "min:10"},
        Message: "Message must be at least 10 characters",
    },
))

Multiple Validation Groups

// Login validation
loginRules := validator.New(
    validator.Field("email", "required", "email"),
    validator.Field("password", "required"),
)

// Registration validation
registerRules := validator.New(
    validator.Field("email", "required", "email"),
    validator.Field("password", "required", "min:8"),
    validator.Field("name", "required", "min:2"),
)

app.Post("/login", loginHandler, loginRules)
app.Post("/register", registerHandler, registerRules)

Query Parameter Validation

// GET /users?page=1&limit=20&status=active
app.Get("/users", listUsers, validator.New(
    validator.OptionalField("page", "integer"),
    validator.OptionalField("limit", "integer"),
    validator.OptionalField("status", "in:active,inactive,pending"),
))

API Reference

Functions

// New creates validator with rules
func New(rules ...Rule) mizu.Middleware

// WithOptions creates validator with full configuration
func WithOptions(opts Options) mizu.Middleware

// JSON validates JSON body against rules
func JSON(rules map[string][]string) mizu.Middleware

// Field creates a required field rule
func Field(name string, rules ...string) Rule

// OptionalField creates an optional field rule
func OptionalField(name string, rules ...string) Rule

Types

type Rule struct {
    Field    string
    Rules    []string
    Message  string
    Optional bool
}

type ValidationError struct {
    Field   string `json:"field"`
    Message string `json:"message"`
}

type ValidationErrors []ValidationError

Field Sources

The validator checks these sources in order:
  1. Query parameters
  2. Form values (POST/PUT)
  3. Headers
  4. Path parameters

Error Response

Default error response format:
{
    "error": "validation failed",
    "errors": [
        {"field": "email", "message": "is required"},
        {"field": "name", "message": "must be at least 2 characters"}
    ]
}

Technical Details

Architecture

The validator middleware is built on a pipeline architecture that processes validation rules sequentially:
  1. Field Value Extraction: The middleware retrieves field values from multiple sources in order of precedence:
    • Query parameters (highest priority)
    • Form values (POST/PUT requests)
    • Headers
    • Path parameters (lowest priority)
  2. Rule Application: Each validation rule is parsed and applied to the field value:
    • Rule format: ruleName or ruleName:parameter
    • Rules are checked sequentially for each field
    • First validation failure stops checking additional rules for that field
  3. Error Handling: Validation errors are collected and either:
    • Passed to a custom error handler (if provided)
    • Returned as JSON with 400 Bad Request (default)

Implementation Details

Validation Flow:
Request β†’ Extract Field Values β†’ Apply Rules β†’ Collect Errors β†’ Error Handler or Next
Rule Parsing:
  • Rules are split on : to separate the rule name from its parameter
  • The applyRule function handles all built-in validation logic
  • Unknown rules are silently ignored
Optional Fields:
  • When a field is marked as optional and empty, all its rules are skipped
  • Empty is defined as an empty string ("")
  • If an optional field has a value, all rules are applied normally
JSON Validation:
  • Reads the entire request body into memory
  • Parses JSON into map[string]any
  • Converts non-string values using stringify helper
  • Supports string, float64, and bool type conversion
Custom Messages:
  • The Message field in a Rule overrides default error messages
  • Custom messages apply to all validation rules for that field
  • If not set, each rule has its own default message

Performance Characteristics

  • Memory: Minimal allocation for most validations; JSON validation reads entire body
  • CPU: Linear with number of fields and rules; regex-free for better performance
  • Concurrency: Safe for concurrent use; no shared state between requests

Best Practices

  • Validate all user input
  • Use appropriate rules for data types
  • Provide clear error messages
  • Validate early in the middleware chain
  • Use optional fields for non-required parameters
  • Combine multiple rules for comprehensive validation
  • Consider custom error handlers for consistent API responses

Testing

Test Coverage

The validator middleware includes comprehensive test coverage for all validation rules and scenarios:
Test CaseDescriptionExpected Behavior
Basic Validation
Valid requestRequest with all required fields meeting validation rulesReturns 200 OK
Missing required fieldRequest missing a field marked as requiredReturns 400 Bad Request
Invalid emailEmail field with invalid format (missing @ or .)Returns 400 Bad Request
Min length violationField value shorter than minimum length requirementReturns 400 Bad Request
Optional Fields
Without optional fieldRequest without an optional field presentReturns 200 OK
With valid optional fieldRequest with optional field that passes validationReturns 200 OK
With invalid optional fieldRequest with optional field failing validationReturns 400 Bad Request
Validation Rules
Required passNon-empty value for required fieldValidation passes
Required failEmpty value for required fieldValidation fails
Min passValue length >= minimumValidation passes
Min failValue length < minimumValidation fails
Max passValue length maximumValidation passes
Max failValue length > maximumValidation fails
Email passValid email format with @ and .Validation passes
Email failInvalid email formatValidation fails
Numeric passValid numeric value (e.g., β€œ123.45”)Validation passes
Numeric failNon-numeric valueValidation fails
Integer passValid integer value (e.g., β€œ123”)Validation passes
Integer failNon-integer value (e.g., β€œ12.3”)Validation fails
Alpha passLetters only valueValidation passes
Alpha failValue with non-letter charactersValidation fails
Alphanum passLetters and numbers onlyValidation passes
Alphanum failValue with special charactersValidation fails
In passValue matching one of allowed optionsValidation passes
In failValue not in allowed options listValidation fails
URL passValid URL with http:// or https://Validation passes
URL failInvalid URL formatValidation fails
UUID passValid UUID format (36 chars with hyphens at positions 8,13,18,23)Validation passes
UUID failInvalid UUID formatValidation fails
Custom Error Handler
Custom error handlerValidation failure with custom error handlerReturns custom status code (422) with custom format
JSON Validation
Valid JSONJSON body with valid fieldsReturns 200 OK
Invalid JSON valuesJSON body with fields failing validationReturns 400 Bad Request
Malformed JSONUnparseable JSON bodyReturns 400 Bad Request
Error Formatting
Multiple validation errorsMultiple fields failing validationReturns formatted error string with all failures
Empty validation errorsNo validation errorsReturns β€œvalidation failed” message
Field Helper Functions
Field creationCreating required field ruleReturns Rule with correct field name and rules
OptionalField creationCreating optional field ruleReturns Rule with Optional=true