Skip to main content

Overview

The bodylimit middleware limits the size of request bodies to protect against large payload attacks and resource exhaustion. Use it when you need:
  • Protection against oversized requests
  • Memory usage control
  • Upload size limits
  • DoS attack prevention

Installation

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

Quick Start

app := mizu.New()

// Limit to 10MB
app.Use(bodylimit.New(bodylimit.MB(10)))

Configuration

Options

OptionTypeDefaultDescription
Limitint641MBMaximum body size in bytes
ErrorHandlerfunc(*mizu.Ctx) error-Custom error handler

Examples

Basic Limit

// 1MB limit (default)
app.Use(bodylimit.New(1 << 20))

// Using helper functions
app.Use(bodylimit.New(bodylimit.KB(500)))  // 500KB
app.Use(bodylimit.New(bodylimit.MB(10)))   // 10MB
app.Use(bodylimit.New(bodylimit.GB(1)))    // 1GB

Custom Error Handler

app.Use(bodylimit.WithHandler(bodylimit.MB(10), func(c *mizu.Ctx) error {
    return c.JSON(413, map[string]string{
        "error":   "Request body too large",
        "max_size": "10MB",
    })
}))

Full Options

app.Use(bodylimit.WithOptions(bodylimit.Options{
    Limit: bodylimit.MB(5),
    ErrorHandler: func(c *mizu.Ctx) error {
        return c.Text(413, "File too large. Maximum size is 5MB.")
    },
}))

Different Limits Per Route

// Global: 1MB
app.Use(bodylimit.New(bodylimit.MB(1)))

// File upload route: 100MB
app.Post("/upload", uploadHandler, bodylimit.New(bodylimit.MB(100)))

// Avatar upload: 2MB
app.Post("/avatar", avatarHandler, bodylimit.New(bodylimit.MB(2)))

API vs Upload Routes

// API routes: small limit
api := app.Group("/api")
api.Use(bodylimit.New(bodylimit.KB(100))) // 100KB for JSON

// Upload routes: large limit
uploads := app.Group("/uploads")
uploads.Use(bodylimit.New(bodylimit.MB(50))) // 50MB for files

API Reference

Functions

// New creates middleware with byte limit
func New(limit int64) mizu.Middleware

// WithHandler creates middleware with custom error handler
func WithHandler(limit int64, handler func(*mizu.Ctx) error) mizu.Middleware

// WithOptions creates middleware with full options
func WithOptions(opts Options) mizu.Middleware

Helper Functions

// KB returns bytes for kilobytes
func KB(n int64) int64

// MB returns bytes for megabytes
func MB(n int64) int64

// GB returns bytes for gigabytes
func GB(n int64) int64

How It Works

  1. Content-Length Check: If Content-Length header exceeds limit, returns 413 immediately
  2. Body Wrapping: Wraps request body with http.MaxBytesReader
  3. Read Enforcement: If body read exceeds limit, returns error

Technical Details

Implementation

The bodylimit middleware uses a two-stage approach to enforce body size limits:
  1. Pre-flight Validation: Before processing the request, it checks the Content-Length header against the configured limit. If the header indicates the body will exceed the limit, the middleware immediately returns a 413 status code without reading the body.
  2. Runtime Enforcement: The middleware wraps the request body with http.MaxBytesReader, which enforces the limit during body reading operations. This catches cases where:
    • The Content-Length header is missing or set to -1 (unknown length)
    • The actual body size differs from the declared Content-Length
    • Chunked transfer encoding is used

Default Behavior

  • Default Limit: 1MB (1 << 20 bytes) when Limit is set to 0 or negative value
  • Default Error Response: Returns HTTP 413 (Request Entity Too Large) with plain text message
  • Body Wrapping: Uses http.MaxBytesReader to wrap the request body, which provides graceful error handling during reads

Error Handling

The middleware supports custom error handlers through the ErrorHandler option. When the limit is exceeded:
  1. If a custom ErrorHandler is configured, it is invoked with the request context
  2. Otherwise, returns default 413 response with status text

Helper Functions

The middleware provides convenient helper functions for common size units:
  • KB(n): Converts kilobytes to bytes (n × 1024)
  • MB(n): Converts megabytes to bytes (n × 1024 × 1024)
  • GB(n): Converts gigabytes to bytes (n × 1024 × 1024 × 1024)

Best Practices

  • Set appropriate limits based on expected data
  • Use smaller limits for JSON APIs
  • Use larger limits for file uploads
  • Consider user experience in error messages
  • Monitor rejected requests

Testing

The bodylimit middleware includes comprehensive test coverage for all functionality:
Test CaseDescriptionExpected Behavior
TestNew/allows small bodyTests that bodies under the limit are acceptedReturns 200 OK and the full body content
TestNew/rejects large body by content-lengthTests Content-Length header validationReturns 413 Request Entity Too Large when Content-Length exceeds limit
TestNew/rejects large body during readTests enforcement during body reading when Content-Length is unknown (-1)Returns error during body read operation
TestWithHandlerTests custom error handler functionalityCalls custom error handler and returns JSON error response with 413 status
TestWithOptions_DefaultTests default 1MB limit when no limit is specifiedAccepts 512KB body with default configuration
TestHelpers/KBTests KB helper function with various inputsCorrectly converts KB to bytes (1KB = 1024, 10KB = 10240)
TestHelpers/MBTests MB helper function with various inputsCorrectly converts MB to bytes (1MB = 1048576, 5MB = 5242880)
TestHelpers/GBTests GB helper function with various inputsCorrectly converts GB to bytes (1GB = 1073741824, 2GB = 2147483648)
TestNew_WithHelpers/allows under limitTests helper functions integrated with New() for bodies under limitAccepts 5KB body with 10KB limit
TestNew_WithHelpers/rejects over limitTests helper functions integrated with New() for bodies over limitRejects 15KB body with 10KB limit, returns 413