Skip to content

Usage

Constructor

func New(engine *guardcore.Engine, opts ...Option) (func(http.Handler) http.Handler, error)

New returns the standard net/http middleware decorator. It rejects a nil engine with an error; invalid option values are silently ignored so a bad flag can never weaken security.

Options

Option Default Purpose
WithMaxBodyBytes(int64) DefaultMaxBodyBytes (262144) Body prefix handed to the engine for inspection
WithLogger(*log.Logger) none Receive fail-closed diagnostics (prefix guardcore nethttp: ...)
guard, err := nethttp.New(engine,
    nethttp.WithMaxBodyBytes(64*1024),
    nethttp.WithLogger(log.New(os.Stderr, "", log.LstdFlags)),
)

Route IDs

Per-route configuration lives in the engine's RouteRegistry. Attach a route ID to the request context before the guard runs by registering the ID middleware first in the chain:

engine.Routes.Register("admin", func(rc *guardcore.RouteConfig) {
    rc.RequiredHeaders = guardcore.RequiredHeaders{
        {Name: "X-Admin-Token", Value: "secret"},
    }
})

routeID := func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if strings.HasPrefix(r.URL.Path, "/admin/") {
            r = r.WithContext(nethttp.WithRouteID(r.Context(), "admin"))
        }
        next.ServeHTTP(w, r)
    })
}

handler := routeID(guard(mux)) // route middleware runs before the guard

Verdicts

When the engine returns a block verdict, the middleware writes the verdict status code, headers, and body, and never calls the wrapped handler:

Situation Status Body
Banned IP 403 IP address banned
Suspicious content 400 Suspicious activity detected
Rate limit exceeded 429 Too many requests

Bodies can be overridden globally through SecurityConfig.CustomErrorResponses.

Fail-closed behavior

If the engine check panics, the middleware recovers, logs through the WithLogger sink, and responds 500 Security check failed rather than letting the request through.