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(),
}