Middleware
Statigo includes a comprehensive middleware pipeline for security, performance, and functionality.
Available Middleware
Logging Middleware
Structured request logging with slog:
r.Use(middleware.StructuredLogger(logger))
Output:
INFO request method=GET path=/en/about status=200 duration=5ms
Compression Middleware
Brotli (preferred) and gzip compression:
r.Use(middleware.Compression())
Automatically compresses: HTML, CSS, JS, JSON, XML, SVG
Rate Limiting Middleware
Token bucket rate limiting:
r.Use(middleware.RateLimiter(middleware.RateLimiterConfig{
RPS: 10, // Requests per second
Burst: 20, // Burst size
}))
Configure via environment:
RATE_LIMIT_RPS=10
RATE_LIMIT_BURST=20
IP Ban Middleware
Block banned IPs with persistent storage:
ipBanList, _ := security.NewIPBanList("data/banned-ips.json", logger)
r.Use(middleware.IPBanMiddleware(ipBanList, logger))
Ban an IP programmatically:
ipBanList.Ban("192.168.1.100", "Abusive behavior", r)
Honeypot Middleware
Trap bots accessing fake admin paths:
honeypotPaths := []string{
"/admin", "/wp-admin", "/wp-login.php",
"/.env", "/.git/config",
}
r.Use(middleware.HoneypotMiddleware(ipBanList, honeypotPaths, logger))
Bots accessing these paths are automatically banned.
Security Headers Middleware
Add security headers:
// Simple preset
r.Use(middleware.SecurityHeadersSimple())
// Or customize
r.Use(middleware.SecurityHeaders(middleware.SecurityHeadersConfig{
CSP: "default-src 'self'",
HSTSEnabled: true,
HSTSMaxAge: 31536000,
FrameOptions: "DENY",
PermissionsPolicy: "geolocation=(), camera=()",
}))
Headers added:
Content-Security-PolicyX-Frame-OptionsX-Content-Type-OptionsStrict-Transport-SecurityPermissions-Policy
Language Middleware
Detect and set language from URL, cookie, or Accept-Language header:
langConfig := middleware.LanguageConfig{
SupportedLanguages: []string{"en", "tr"},
DefaultLanguage: "en",
SkipPaths: []string{"/robots.txt", "/sitemap.xml"},
SkipPrefixes: []string{"/static/", "/health/"},
}
r.Use(middleware.Language(i18nInstance, langConfig))
Detection priority:
- URL path prefix (
/en/,/tr/) - Cookie (
lang) Accept-Languageheader- Default language
Caching Headers Middleware
Add browser cache headers:
r.Use(middleware.CachingHeaders(devMode))
Cache behavior:
- Dev mode:
no-cache - Production: Based on route strategy
Layout Data Middleware
Inject shared data into all templates:
layoutData := map[string]interface{}{
"SiteName": "My Site",
"Year": 2024,
}
r.Use(middleware.LayoutDataMiddleware(layoutData))
Access in templates:
<h1>{{.SiteName}}</h1>
Canonical Path Middleware
Store and validate canonical paths:
r.Use(router.CanonicalPathMiddleware(routeRegistry))
Cache Middleware
Response caching with automatic invalidation:
r.Use(middleware.CacheMiddleware(cacheManager, logger))
Webhook Auth Middleware
Validate webhook requests:
r.Use(middleware.WebhookAuthMiddleware("my-secret-key"))
Middleware Order
The recommended order is important:
r.Use(middleware.StructuredLogger(logger)) // 1. Log everything
r.Use(chiMiddleware.Recoverer) // 2. Panic recovery
r.Use(middleware.IPBanMiddleware(ipBanList, logger)) // 3. Block banned IPs
r.Use(middleware.HoneypotMiddleware(ipBanList, paths, logger)) // 4. Trap bots
r.Use(middleware.RateLimiter(config)) // 5. Rate limit
r.Use(middleware.Compression()) // 6. Compress responses
r.Use(middleware.SecurityHeadersSimple()) // 7. Security headers
r.Use(middleware.CachingHeaders(devMode)) // 8. Cache headers
r.Use(middleware.Language(i18nInstance, config)) // 9. Language detection
r.Use(router.CanonicalPathMiddleware(routeRegistry)) // 10. Validate paths
r.Use(middleware.CacheMiddleware(cacheManager, logger)) // 11. Response cache
Custom Middleware
Create your own middleware:
func MyMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Before request
start := time.Now()
// Call next handler
next.ServeHTTP(w, r)
// After request
duration := time.Since(start)
log.Println("Request took", duration)
})
}
Use it:
r.Use(MyMiddleware)
Chi Middleware
Statigo is built on chi. You can use any chi middleware:
import chiMiddleware "github.com/go-chi/chi/middleware"
r.Use(chiMiddleware.RequestID)
r.Use(chiMiddleware.RealIP)
r.Use(chiMiddleware.Logger)
r.Use(chiMiddleware.Recoverer)
See chi documentation for more.