Middleware
Middleware in Nimbus is registered in start/kernel.go, following Laravel-style middleware layering. The kernel organises middleware into three layers: server, router, and named.
The HTTP Kernel
start/kernel.go is the single place where all middleware is configured:
// start/kernel.go
package start
import (
"github.com/CodeSyncr/nimbus"
"github.com/CodeSyncr/nimbus/middleware"
"github.com/CodeSyncr/nimbus/router"
)
func RegisterMiddleware(app *nimbus.App) {
// Server Middleware
// Runs on every HTTP request, even if there is no route
// registered for the request URL.
app.Router.Use(
middleware.Logger(),
middleware.Recover(),
)
// Router Middleware
// Runs on all HTTP requests with a registered route.
// app.Router.Use(
// middleware.CORS("*"),
// middleware.CSRF(middleware.NewMemoryCSRFStore()),
// )
}
// Named Middleware
// Must be explicitly assigned to routes or route groups.
var Middleware = map[string]router.Middleware{
// "auth": middleware.RequireAuth(),
// "guest": guestMiddleware(),
}
Server middleware
Server middleware runs on every HTTP request — even if no route matches. Use this for logging, panic recovery, and other concerns that apply globally.
Router middleware
Router middleware runs only on requests that match a registered route. CORS, CSRF, body parsing, and session middleware belong here.
Named middleware
Named middleware is defined as a map in kernel.go and assigned to individual routes or groups in start/routes.go:
// start/routes.go
import "myapp/start"
admin := app.Router.Group("/admin", start.Middleware["auth"])
admin.Get("/dashboard", dashboardHandler)
Built-in middleware
Logger
Logs method, path, client IP, and duration.
middleware.Logger()
Recover
Recovers panics and returns a 500 JSON response.
middleware.Recover()
CORS
Sets Access-Control-Allow-Origin and related headers. Parameter: origin string.
middleware.CORS("*")
CSRF
Validates token for non-GET/HEAD/OPTIONS. Token from header X-CSRF-Token or form csrf_token.
store := middleware.NewMemoryCSRFStore()
middleware.CSRF(store)
RateLimit
Parameters: limit int, window time.Duration, keyFn func(*http.Request) string. Returns 429 when exceeded.
middleware.RateLimit(60, time.Minute, func(r *http.Request) string {
return r.RemoteAddr
})
RequestID
Generates a unique request ID for every request. Set via X-Request-Id response header and stored in context (c.Get("request_id")). Reuses incoming X-Request-Id when present (useful behind load balancers).
middleware.RequestID()
Timeout
Wraps each request with a context deadline. If the handler does not complete within the given duration, the context is cancelled.
middleware.Timeout(30 * time.Second)
BodyLimit
Limits the size of the request body. Returns 413 Request Entity Too Large when exceeded.
middleware.BodyLimit(10 * 1024 * 1024) // 10 MB
Gzip
Compresses response bodies using gzip when the client supports it. Responses smaller than 256 bytes are not compressed.
middleware.Gzip()
SecureHeaders
Adds production-ready security headers (HSTS, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, etc.).
middleware.SecureHeaders(middleware.SecureHeadersConfig{
HSTS: true,
HSTSMaxAge: 31536000, // 1 year
FrameOptions: "DENY",
ContentTypeNoSniff: true,
XSSProtection: true,
})
// Or use defaults:
middleware.SecureHeaders(middleware.SecureHeadersConfig{})
TrustedProxies
Strips forwarded-for headers from untrusted proxy IPs. Only preserves X-Forwarded-For, X-Real-IP, etc. from trusted CIDR ranges.
middleware.TrustedProxies("10.0.0.0/8", "172.16.0.0/12")
Metrics
Records Prometheus-compatible HTTP metrics: request count, duration histogram, in-flight gauge, and response size. See the Metrics page for details.
middleware.Metrics()
Custom middleware
Create custom middleware in app/middleware/. Middleware has type func(HandlerFunc) HandlerFunc:
// app/middleware/tenant.go
package middleware
import (
"github.com/CodeSyncr/nimbus/context"
"github.com/CodeSyncr/nimbus/router"
)
func Tenant() router.Middleware {
return func(next router.HandlerFunc) router.HandlerFunc {
return func(c *http.Context) error {
// before handler
err := next(c)
// after handler
return err
}
}
}
Then register it in the kernel:
// start/kernel.go
import appmw "myapp/app/middleware"
var Middleware = map[string]router.Middleware{
"auth": middleware.RequireAuth(),
"tenant": appmw.Tenant(),
}