Files
common/xff/echo/echo.go
Ask Bjørn Hansen 1b9e566892 refactor(xff): split into generic, echo, and fastly packages
Extract generic trusted proxy handling into xff/ (stdlib only),
Echo framework adapter into xff/echo/, and slim xff/fastlyxff/
down to Fastly JSON loading.

Key changes:
- xff/ uses netip.Prefix for efficient IP matching
- Fix XFF extraction to walk right-to-left per MDN spec
- Remove echo dependency from core xff package
- fastlyxff.New() now returns *xff.TrustedProxies
2026-03-21 18:41:28 -07:00

49 lines
1.1 KiB
Go

// Package xffecho adapts [xff.TrustedProxies] for use with the Echo web
// framework's X-Forwarded-For IP extraction.
//
// # Usage
//
// tp, err := fastlyxff.New("fastly.json")
// if err != nil {
// return err
// }
// trustOpts := xffecho.TrustOptions(tp)
// e.IPExtractor = echo.ExtractIPFromXFFHeader(trustOpts...)
package xffecho
import (
"net"
"net/netip"
"github.com/labstack/echo/v4"
"go.ntppool.org/common/xff"
)
// TrustOptions converts a [xff.TrustedProxies] into Echo trust options
// for use with [echo.ExtractIPFromXFFHeader].
func TrustOptions(tp *xff.TrustedProxies) []echo.TrustOption {
prefixes := tp.Prefixes()
opts := make([]echo.TrustOption, 0, len(prefixes))
for _, p := range prefixes {
opts = append(opts, echo.TrustIPRange(prefixToIPNet(p)))
}
return opts
}
// prefixToIPNet bridges netip.Prefix (used by xff) to net.IPNet (used by Echo).
func prefixToIPNet(p netip.Prefix) *net.IPNet {
addr := p.Masked().Addr()
bits := p.Bits()
ipLen := 128
if addr.Is4() {
ipLen = 32
}
return &net.IPNet{
IP: net.IP(addr.AsSlice()),
Mask: net.CIDRMask(bits, ipLen),
}
}