Skip to main content

Overview

The forwarded middleware parses X-Forwarded-* headers set by load balancers and proxies, extracting client IP, protocol, host, and other forwarded information.

Installation

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

Quick Start

app := mizu.New()
app.Use(forwarded.New())

Configuration

OptionTypeDefaultDescription
TrustProxybooltrueTrust forwarded headers
TrustedProxies[]string-List of trusted proxy IPs/CIDRs

Headers Parsed

HeaderInformation
X-Forwarded-ForClient IP chain
X-Forwarded-HostOriginal host
X-Forwarded-ProtoProtocol (http/https)
X-Forwarded-PortOriginal port
X-Forwarded-PrefixPath prefix
ForwardedRFC 7239 header

Examples

Basic Usage

app.Use(forwarded.New())

app.Get("/", func(c *mizu.Ctx) error {
    info := forwarded.Get(c)
    return c.JSON(200, map[string]any{
        "clientIP": info.ClientIP,
        "proto":    info.Proto,
        "host":     info.Host,
    })
})

Trusted Proxies Only

app.Use(forwarded.WithOptions(forwarded.Options{
    TrustProxy: true,
    TrustedProxies: []string{
        "10.0.0.0/8",
        "192.168.1.0/24",
    },
}))

Helper Functions

// Get client IP
ip := forwarded.ClientIP(c)

// Get protocol
proto := forwarded.Proto(c)

// Get host
host := forwarded.Host(c)

Info Struct

type Info struct {
    For      string    // X-Forwarded-For value
    Host     string    // Original host
    Proto    string    // http or https
    Port     string    // Original port
    Prefix   string    // Path prefix
    ClientIP net.IP    // Parsed client IP
}

API Reference

func New() mizu.Middleware
func WithOptions(opts Options) mizu.Middleware
func Get(c *mizu.Ctx) *Info
func FromContext(c *mizu.Ctx) *Info
func ClientIP(c *mizu.Ctx) net.IP
func Proto(c *mizu.Ctx) string
func Host(c *mizu.Ctx) string

Technical Details

Header Processing Priority

The middleware processes headers in the following order:
  1. X-Forwarded-For: Extracts the client IP from the first entry in the comma-separated list
  2. X-Forwarded-Host: Sets the original host requested by the client
  3. X-Forwarded-Proto: Determines if the original request was HTTP or HTTPS
  4. X-Forwarded-Port: Captures the original port number
  5. X-Forwarded-Prefix: Records any path prefix added by reverse proxies
  6. Forwarded (RFC 7239): Parses the standardized Forwarded header, which can override previous values

Trusted Proxy Validation

When TrustedProxies is configured:
  • IP addresses are automatically converted to CIDR notation (single IPs get /32)
  • The middleware checks if the remote address matches any trusted CIDR ranges
  • If no match is found, all X-Forwarded-* headers are ignored and the remote address is used

IP Parsing

The middleware handles various IP address formats:
  • Standard IPv4 addresses (e.g., 192.168.1.1)
  • IPv6 addresses in RFC 7239 format with brackets (e.g., [2001:db8::1])
  • Addresses with port numbers (automatically stripped)

Context Storage

Forwarded information is stored in the request context using a private context key, making it accessible throughout the request lifecycle via helper functions.

Best Practices

  1. Always specify trusted proxies in production environments to prevent header spoofing
  2. Use CIDR notation for trusted proxy ranges to cover entire subnets
  3. Validate client IPs after extraction if using them for security decisions
  4. Prefer RFC 7239 Forwarded header when possible for better standardization
  5. Disable TrustProxy when not behind a reverse proxy to avoid security issues

Testing

The middleware includes comprehensive test coverage for various scenarios:
Test CaseDescriptionExpected Behavior
TestNewBasic middleware functionality with X-Forwarded headersCorrectly parses X-Forwarded-For, X-Forwarded-Proto, and X-Forwarded-Host
TestWithOptions_TrustedProxies (trusted proxy)Request from a trusted proxy IPHonors X-Forwarded-For header and extracts client IP
TestWithOptions_TrustedProxies (untrusted proxy)Request from an untrusted proxy IPIgnores X-Forwarded-For and uses RemoteAddr instead
TestWithOptions_XForwardedForMultipleMultiple IPs in X-Forwarded-For chainExtracts the first (original client) IP from the chain
TestWithOptions_ForwardedHeaderRFC 7239 Forwarded header parsingCorrectly parses for, proto, and host from Forwarded header
TestFromContextAlias function for Get()FromContext returns same result as Get()
TestClientIPClientIP helper functionReturns parsed client IP as net.IP
TestProto (with header)Protocol extraction with X-Forwarded-ProtoReturns “https” when header is present
TestProto (without header)Protocol extraction without headerReturns default “http” when no header present
TestHostHost extraction from X-Forwarded-HostReturns forwarded host value
TestWithOptions_DisableTrustProxyTrustProxy disabledIgnores all X-Forwarded headers and uses RemoteAddr

Security Note

Only enable TrustProxy when behind a trusted proxy. Untrusted clients can spoof these headers.