Middleware Reference
2 minute read
The router includes production-ready middleware in separate packages. Each middleware is its own Go module, so you only add the ones you need and keep your dependency footprint small. All of them use functional options for configuration.
Security
Security Headers
Package: rivaas.dev/middleware/security
go get rivaas.dev/middleware/security
import "rivaas.dev/middleware/security"
r.Use(security.New(
security.WithHSTS(true),
security.WithFrameDeny(true),
security.WithContentTypeNosniff(true),
security.WithXSSProtection(true),
))
CORS
Package: rivaas.dev/middleware/cors
go get rivaas.dev/middleware/cors
import "rivaas.dev/middleware/cors"
r.Use(cors.New(
cors.WithAllowedOrigins("https://example.com"),
cors.WithAllowedMethods("GET", "POST", "PUT", "DELETE"),
cors.WithAllowedHeaders("Content-Type", "Authorization"),
cors.WithAllowCredentials(true),
cors.WithMaxAge(3600),
))
Basic Auth
Package: rivaas.dev/middleware/basicauth
go get rivaas.dev/middleware/basicauth
import "rivaas.dev/middleware/basicauth"
admin := r.Group("/admin")
admin.Use(basicauth.New(
basicauth.WithCredentials("admin", "secret"),
basicauth.WithRealm("Admin Area"),
))
Observability
Access Log
Package: rivaas.dev/middleware/accesslog
go get rivaas.dev/middleware/accesslog
import (
"log/slog"
"rivaas.dev/middleware/accesslog"
)
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
r.Use(accesslog.New(
accesslog.WithLogger(logger),
accesslog.WithExcludePaths("/health", "/metrics"),
accesslog.WithSampleRate(0.1),
accesslog.WithSlowThreshold(500 * time.Millisecond),
))
Request ID
Package: rivaas.dev/middleware/requestid
go get rivaas.dev/middleware/requestid
Generates unique, time-ordered request IDs for distributed tracing and log correlation.
import "rivaas.dev/middleware/requestid"
// UUID v7 by default (36 chars, time-ordered, RFC 9562)
r.Use(requestid.New())
// Use ULID for shorter IDs (26 chars)
r.Use(requestid.New(requestid.WithULID()))
// Custom header name
r.Use(requestid.New(requestid.WithHeader("X-Correlation-ID")))
// Get request ID in handlers
func handler(c *router.Context) {
id := requestid.Get(c)
}
ID Formats:
- UUID v7 (default):
018f3e9a-1b2c-7def-8000-abcdef123456 - ULID:
01ARZ3NDEKTSV4RRFFQ69G5FAV
Reliability
Recovery
Package: rivaas.dev/middleware/recovery
go get rivaas.dev/middleware/recovery
import "rivaas.dev/middleware/recovery"
r.Use(recovery.New(
recovery.WithPrintStack(true),
recovery.WithLogger(logger),
))
Timeout
Package: rivaas.dev/middleware/timeout
go get rivaas.dev/middleware/timeout
import "rivaas.dev/middleware/timeout"
r.Use(timeout.New(
timeout.WithDuration(30 * time.Second),
timeout.WithMessage("Request timeout"),
))
Rate Limit
Package: rivaas.dev/middleware/ratelimit
go get rivaas.dev/middleware/ratelimit
import "rivaas.dev/middleware/ratelimit"
r.Use(ratelimit.New(
ratelimit.WithRequestsPerSecond(1000),
ratelimit.WithBurst(100),
ratelimit.WithKeyFunc(func(c *router.Context) string {
return c.ClientIP() // Rate limit by IP
}),
ratelimit.WithLogger(logger),
))
Body Limit
Package: rivaas.dev/middleware/bodylimit
go get rivaas.dev/middleware/bodylimit
import "rivaas.dev/middleware/bodylimit"
r.Use(bodylimit.New(
bodylimit.WithLimit(10 * 1024 * 1024), // 10MB
))
Performance
Compression
Package: rivaas.dev/middleware/compression
go get rivaas.dev/middleware/compression
import "rivaas.dev/middleware/compression"
r.Use(compression.New(
compression.WithLevel(compression.DefaultCompression),
compression.WithMinSize(1024), // Don't compress <1KB
compression.WithLogger(logger),
))
Other
Method Override
Package: rivaas.dev/middleware/methodoverride
go get rivaas.dev/middleware/methodoverride
import "rivaas.dev/middleware/methodoverride"
r.Use(methodoverride.New(
methodoverride.WithHeader("X-HTTP-Method-Override"),
))
Trailing Slash
Package: rivaas.dev/middleware/trailingslash
go get rivaas.dev/middleware/trailingslash
import "rivaas.dev/middleware/trailingslash"
r.Use(trailingslash.New(
trailingslash.WithRedirectCode(301),
))
Middleware Ordering
Recommended middleware order:
r := router.New()
// 1. Request ID
r.Use(requestid.New())
// 2. AccessLog
r.Use(accesslog.New())
// 3. Recovery
r.Use(recovery.New())
// 4. Security/CORS
r.Use(security.New())
r.Use(cors.New())
// 5. Body Limit
r.Use(bodylimit.New())
// 6. Rate Limit
r.Use(ratelimit.New())
// 7. Timeout
r.Use(timeout.New())
// 8. Authentication
r.Use(auth.New())
// 9. Compression (last)
r.Use(compression.New())
Complete Example
package main
import (
"log/slog"
"net/http"
"os"
"time"
"rivaas.dev/router"
"rivaas.dev/middleware/accesslog"
"rivaas.dev/middleware/cors"
"rivaas.dev/middleware/recovery"
"rivaas.dev/middleware/requestid"
"rivaas.dev/middleware/security"
)
func main() {
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
r := router.New()
// Observability
r.Use(requestid.New())
r.Use(accesslog.New(
accesslog.WithLogger(logger),
accesslog.WithExcludePaths("/health"),
))
// Reliability
r.Use(recovery.New())
// Security
r.Use(security.New())
r.Use(cors.New(
cors.WithAllowedOrigins("*"),
cors.WithAllowedMethods("GET", "POST", "PUT", "DELETE"),
))
r.GET("/", func(c *router.Context) {
c.JSON(200, map[string]string{"message": "Hello"})
})
http.ListenAndServe(":8080", r)
}
Next Steps
- Middleware Guide: See middleware usage
- Source Code: Browse middleware source
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.