Security

Middleware

Security headers, CSRF, rate limiting, flash messages, and more.

HAMR's pkg/middleware package ships with all the middleware you need for a production web app: security headers, CSRF protection, rate limiting, flash messages, audit logging, and CORS. Each is opt-in and applied per route group.

Secure headers

SecureWithConfig sets X-Frame-Options, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy, and a configurable Content-Security-Policy.

server.go
csp := "default-src 'self'; script-src 'self' 'unsafe-inline'; " +
       "style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:"

site.Use(hamrmw.SecureWithConfig(hamrmw.SecureConfig{
    ContentSecurityPolicy: csp,
}))

CSRF

HAMR uses double-submit cookies for CSRF. The middleware sets a token cookie and expects the same token in a header (X-CSRF-Token) or form field (csrf_token) on mutating requests.

server.go
site.Use(hamrmw.CSRFWithConfig(hamrmw.CSRFConfig{
    Secure: !devMode,
}))

Forms include the token via the helper component, and the layout's HTMX config injects it on every HTMX request automatically:

login.templ
<form method="POST" action="/login">
    @form.CSRFField(c)
    <input type="email" name="email"/>
    <input type="password" name="password"/>
    <button type="submit">Sign in</button>
</form>

Flash messages

FlashWithConfig stores one-time flash messages in a signed cookie. They're consumed on the next request and rendered by your layout.

handler.go
import "github.com/FyrmForge/hamr/pkg/middleware"

func (h *handler) Create(c echo.Context) error {
    // ... create the resource ...
    middleware.SetFlash(c, middleware.FlashSuccess, "Book created!")
    return respond.Redirect(c, "/books")
}

Rate limiting

RateLimit is a token bucket limiter with pluggable storage — in-memory for single-instance apps, PostgreSQL for distributed setups.

server.go
store := hamrmw.NewMemoryRateLimitStore()
api.Use(hamrmw.RateLimitWithConfig(hamrmw.RateLimitConfig{
    Store: store,
    Rate:  100,
    Burst: 200,
    Window: time.Minute,
}))

Audit logging

Audit automatically logs mutating HTTP requests (POST/PUT/DELETE/PATCH) along with the authenticated subject ID. Pair it with structured logging and you have a complete audit trail.

CORS

server.go
srv.Echo().Use(hamrmw.CORSWithConfig(hamrmw.CORSConfig{
    AllowOrigins:     []string{"https://example.com"},
    AllowCredentials: true,
}))
Layered defaults
You don't need to configure all of these. Start with the defaults that hamr new generates and tune what you need. Every middleware has a sensible zero-config default.