Skip to main content

Overview

The filter middleware provides request filtering capabilities, allowing or blocking requests based on custom conditions. Use it when you need:
  • Block specific requests
  • Conditional access
  • Request validation

Installation

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

Quick Start

app := mizu.New()

// Block requests without API key
app.Use(filter.New(func(c *mizu.Ctx) bool {
    return c.Request().Header.Get("X-API-Key") != ""
}))

Configuration

Options

OptionTypeDefaultDescription
Allowfunc(*mizu.Ctx) boolRequiredAllow function
ErrorHandlerfunc(*mizu.Ctx) error403Custom rejection

Examples

Allow Function

app.Use(filter.New(func(c *mizu.Ctx) bool {
    // Allow if condition is true
    return isAllowed(c)
}))

Block by User-Agent

app.Use(filter.New(func(c *mizu.Ctx) bool {
    ua := c.Request().UserAgent()
    return !strings.Contains(ua, "BadBot")
}))

Custom Error

app.Use(filter.WithOptions(filter.Options{
    Allow: allowFunc,
    ErrorHandler: func(c *mizu.Ctx) error {
        return c.JSON(403, map[string]string{
            "error": "Access denied",
        })
    },
}))

Combine Conditions

app.Use(filter.New(func(c *mizu.Ctx) bool {
    hasKey := c.Request().Header.Get("X-API-Key") != ""
    isGet := c.Request().Method == http.MethodGet
    return hasKey || isGet
}))

API Reference

Functions

// New creates filter middleware
func New(allow func(*mizu.Ctx) bool) mizu.Middleware

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

// Block creates blocking filter
func Block(block func(*mizu.Ctx) bool) mizu.Middleware

Technical Details

The filter middleware provides comprehensive request filtering through multiple criteria:

Pattern Matching

The middleware uses glob-to-regex conversion for flexible pattern matching:
  • * - Matches any characters except path separators (e.g., /api/* matches /api/users but not /api/users/1)
  • ** - Matches any characters including path separators (e.g., /admin/** matches /admin/deep/nested/path)
  • ? - Matches exactly one character
Special regex characters (., +, ^, $, |, etc.) are automatically escaped.

Filter Evaluation Order

Filters are evaluated in the following order:
  1. HTTP Methods - Check if method is in AllowedMethods (if configured)
  2. Blocked Hosts - Check if host is in BlockedHosts (takes precedence over allowed)
  3. Allowed Hosts - Check if host is in AllowedHosts (if configured)
  4. Blocked Paths - Check if path matches BlockedPaths patterns (takes precedence over allowed)
  5. Allowed Paths - Check if path matches AllowedPaths patterns (if configured)
  6. Blocked User Agents - Check if UA matches BlockedUserAgents patterns (takes precedence over allowed)
  7. Allowed User Agents - Check if UA matches AllowedUserAgents patterns (if configured)
  8. Custom Filter - Execute CustomFilter function if provided
If any check fails, the request is blocked and the OnBlock handler is called (or returns 403 Forbidden by default).

Host Normalization

Host names are normalized by:
  • Converting to lowercase for case-insensitive matching
  • Stripping port numbers (e.g., example.com:8080 becomes example.com)

Performance Optimization

  • HTTP methods are stored in a map for O(1) lookup
  • Hosts are stored in maps for O(1) lookup
  • Glob patterns are compiled to regex once during initialization
  • All patterns are pre-compiled to avoid runtime compilation overhead

Best Practices

  • Keep filter logic simple
  • Log blocked requests
  • Use descriptive error messages
  • Combine with rate limiting

Testing

The filter middleware includes comprehensive test coverage for all filtering scenarios:
Test CaseDescriptionExpected Behavior
TestNewCreates filter with default optionsAllows all requests to pass through
TestMethods (allowed)Filters by HTTP method - allowed methodReturns 200 OK for GET request
TestMethods (blocked)Filters by HTTP method - blocked methodReturns 403 Forbidden for DELETE request
TestBlockPaths (allowed)Blocks specific path patterns - allowed pathReturns 200 OK for root path
TestBlockPaths (admin)Blocks admin paths with * wildcardReturns 403 Forbidden for /admin/users
TestBlockPaths (deep)Blocks deep paths with ** wildcardReturns 403 Forbidden for /internal/deep/path
TestPaths (allowed)Allows only specific path patternsReturns 200 OK for /api/users
TestPaths (blocked)Blocks paths not in allow listReturns 403 Forbidden for /secret
TestHosts (allowed)Filters by hostname - allowed hostReturns 200 OK for example.com
TestHosts (blocked)Filters by hostname - blocked hostReturns 403 Forbidden for evil.com
TestBlockUserAgents (allowed)Blocks specific user agents - allowed UAReturns 200 OK for Mozilla/5.0
TestBlockUserAgents (curl)Blocks curl user agent patternReturns 403 Forbidden for curl/7.68.0
TestBlockUserAgents (bot)Blocks bot user agent patternReturns 403 Forbidden for Googlebot/2.1
TestCustomFilter (passes)Custom filter function returns trueReturns 200 OK when X-Secret header is valid
TestCustomFilter (fails)Custom filter function returns falseReturns 403 Forbidden when X-Secret header missing
TestCustomOnBlockCustom OnBlock handlerReturns 405 with JSON error message
TestBlockedHosts (allowed)Blocks specific hosts - allowed hostReturns 200 OK for example.com
TestBlockedHosts (blocked)Blocks specific hosts - blocked hostReturns 403 Forbidden for spam.com
TestGlobToRegex (/api/*)Glob pattern with single wildcardMatches /api/users but not /api/users/1
TestGlobToRegex (/api/**)Glob pattern with double wildcardMatches /api/users/1 (nested paths)
TestGlobToRegex (*.txt)File extension patternMatches file.txt but not file.json
TestGlobToRegex (/a?c)Question mark single char matchMatches /abc
TestGlobToRegex (/a.b)Dot character escapingMatches literal /a.b