rest

package module
v1.21.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 8, 2026 License: MIT Imports: 32 Imported by: 70

README

REST helpers and middleware Build Status Go Report Card Coverage Status godoc

Install and update

go get -u github.com/go-pkgz/rest

Middlewares

AppInfo middleware

Adds info to every response header:

  • App-Name - application name
  • App-Version - application version
  • Org - organization
  • M-Host - host name from instance-level $MHOST env

Ping-Pong middleware

Responds with pong on GET /ping. Also, responds to anything with /ping suffix, like /v2/ping.

Example for both:

> http GET https://remark42.radio-t.com/ping

HTTP/1.1 200 OK
Date: Sun, 15 Jul 2018 19:40:31 GMT
Content-Type: text/plain
Content-Length: 4
Connection: keep-alive
App-Name: remark42
App-Version: master-ed92a0b-20180630-15:59:56
Org: Umputun

pong

Health middleware

Responds with the status 200 if all health checks passed, 503 if any failed. Both health path and check functions passed by consumer. For production usage this middleware should be used with throttler/limiter and, optionally, with some auth middlewares

Example of usage:

    check1 := func(ctx context.Context) (name string, err error) {
        // do some check, for example check DB connection		
		return "check1", nil // all good, passed
    }
    check2 := func(ctx context.Context) (name string, err error) {
        // do some other check, for example ping an external service		
		return "check2", errors.New("some error") // check failed
    }

    router := chi.NewRouter()
	router.Use(rest.Health("/health", check1, check2))

example of the actual call and response:

> http GET https://example.com/health

HTTP/1.1 503 Service Unavailable
Date: Sun, 15 Jul 2018 19:40:31 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 36

[
    {"name":"check1","status":"ok"},
    {"name":"check2","status":"failed","error":"some error"}
]

this middleware is pretty basic, but can be used for simple health checks. For more complex cases, like async/cached health checks see alexliesenfeld/health

Logger middleware

Logs request, request handling time and response. Log record fields in order of occurrence:

  • Request's HTTP method
  • Requested URL (with sanitized query)
  • Remote IP
  • Response's HTTP status code
  • Response body size
  • Request handling time
  • Userinfo associated with the request (optional)
  • Request subject (optional)
  • Request ID (if X-Request-ID present)
  • Request body (optional)

remote IP can be masked with user defined function

example: 019/03/05 17:26:12.976 [INFO] GET - /api/v1/find?site=remark - 8e228e9cfece - 200 (115) - 4.47784618s

Recoverer middleware

Recoverer is a middleware that recovers from panics, logs the panic (and a backtrace), and returns an HTTP 500 (Internal Server Error) status if possible. It prevents server crashes in case of panic in one of the controllers.

OnlyFrom middleware

OnlyFrom middleware allows access from a limited list of source IPs. Such IPs can be defined as complete ip (like 192.168.1.12), prefix (129.168.) or CIDR (192.168.0.0/16). The middleware will respond with StatusForbidden (403) if the request comes from a different IP. It supports both IPv4 and IPv6 and checks the usual headers like X-Forwarded-For and X-Real-IP and the remote address.

Note: headers should be trusted and set by a proxy, otherwise it is possible to spoof them.

Metrics middleware

Metrics middleware responds to GET /metrics with list of expvar. Optionally allows a restricted list of source ips.

BlackWords middleware

BlackWords middleware doesn't allow user-defined words in the request body.

SizeLimit middleware

SizeLimit middleware checks if body size is above the limit and returns StatusRequestEntityTooLarge (413)

Trace middleware

The Trace middleware is designed to add request tracing functionality. It looks for the X-Request-ID header in the incoming HTTP request. If not found, a random ID is generated. This trace ID is then set in the response headers and added to the request's context.

Deprecation middleware

Adds the HTTP Deprecation response header, see draft-ietf-httpapi-deprecation-header-02

BasicAuth middleware

BasicAuth middleware requires basic auth and matches user & passwd with client-provided checker. In case if no basic auth headers returns StatusUnauthorized, in case if checker failed - StatusForbidden

Rewrite middleware

The Rewrite middleware is designed to rewrite the URL path based on a given rule, similar to how URL rewriting is done in nginx. It supports regular expressions for pattern matching and prevents multiple rewrites.

For example, Rewrite("^/sites/(.*)/settings/$", "/sites/settings/$1") will change request's URL from /sites/id1/settings/ to /sites/settings/id1

CleanPath middleware

Cleans double slashes from URL path. For example, requests to /users//1 or //users////1 will be cleaned to /users/1 before routing. Trailing slashes are preserved: /api//v1/ becomes /api/v1/. Note: dot segments (. and ..) are intentionally not cleaned to preserve routing semantics.

router.Use(rest.CleanPath)

StripSlashes middleware

Removes trailing slashes from URL path. For example, /users/ becomes /users. The root path / is preserved.

router.Use(rest.StripSlashes)

NoCache middleware

Sets a number of HTTP headers to prevent a router (handler's) response from being cached by an upstream proxy and/or client.

Headers middleware

Sets headers (passed as key:value) to requests. I.e. rest.Headers("Server:MyServer", "X-Blah:Foo")

Gzip middleware

Compresses response with gzip.

RealIP middleware

RealIP is a middleware that sets a http.Request's RemoteAddr to the results of parsing various headers that contain the client's real IP address. It checks headers in the following priority order:

  1. X-Real-IP - trusted proxy (nginx/reproxy) sets this to actual client
  2. CF-Connecting-IP - Cloudflare's header for original client
  3. X-Forwarded-For - leftmost public IP (original client in CDN/proxy chain)
  4. RemoteAddr - fallback for direct connections

Only public IPs are accepted from headers; private/loopback/link-local IPs are skipped. This makes the middleware compatible with CDN setups like Cloudflare where the leftmost IP in X-Forwarded-For is the actual client.

CORS middleware

Handles Cross-Origin Resource Sharing, allowing controlled access from different origins.

// allow all origins (default)
router.Use(rest.CORS())

// specific origins with credentials
router.Use(rest.CORS(
    rest.CorsAllowedOrigins("https://app.example.com", "https://admin.example.com"),
    rest.CorsAllowCredentials(true),
    rest.CorsMaxAge(86400),
))

// full configuration
router.Use(rest.CORS(
    rest.CorsAllowedOrigins("https://app.example.com"),
    rest.CorsAllowedMethods("GET", "POST", "PUT", "DELETE"),
    rest.CorsAllowedHeaders("Authorization", "Content-Type", "X-Custom-Header"),
    rest.CorsExposedHeaders("X-Request-Id", "X-Total-Count"),
    rest.CorsAllowCredentials(true),
    rest.CorsMaxAge(3600),
))

Features:

  • Automatic preflight (OPTIONS) handling
  • Origin validation with case-insensitive matching
  • Credentials support (reflects origin instead of *)
  • Configurable cache duration for preflight results

Available options:

  • CorsAllowedOrigins(origins...) - allowed origins (default: *)
  • CorsAllowedMethods(methods...) - allowed HTTP methods (default: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD)
  • CorsAllowedHeaders(headers...) - allowed request headers (default: Accept, Content-Type, Authorization, X-Requested-With)
  • CorsExposedHeaders(headers...) - headers exposed to client
  • CorsAllowCredentials(bool) - enable credentials (cookies, auth headers)
  • CorsMaxAge(seconds) - preflight cache duration

Secure middleware

Adds security headers to responses. By default sets: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, X-XSS-Protection, and Strict-Transport-Security (for HTTPS only).

// with sensible defaults
router.Use(rest.Secure())

// with full security headers for web apps (adds CSP and Permissions-Policy)
router.Use(rest.Secure(rest.SecAllHeaders()))

// with custom options
router.Use(rest.Secure(
    rest.SecFrameOptions("SAMEORIGIN"),
    rest.SecReferrerPolicy("no-referrer"),
    rest.SecHSTS(86400, true, true),
    rest.SecContentSecurityPolicy("default-src 'self'"),
    rest.SecPermissionsPolicy("geolocation=(), camera=()"),
))

Default headers:

  • X-Frame-Options: DENY - prevents clickjacking
  • X-Content-Type-Options: nosniff - prevents MIME-type sniffing
  • Referrer-Policy: strict-origin-when-cross-origin - controls referrer information
  • X-XSS-Protection: 1; mode=block - enables XSS filtering (legacy browsers)
  • Strict-Transport-Security: max-age=31536000; includeSubDomains - enforces HTTPS (only sent over HTTPS)

Available options:

  • SecFrameOptions(value) - set X-Frame-Options (DENY, SAMEORIGIN)
  • SecContentTypeNosniff(enable) - enable/disable nosniff
  • SecReferrerPolicy(policy) - set Referrer-Policy
  • SecContentSecurityPolicy(policy) - set Content-Security-Policy
  • SecPermissionsPolicy(policy) - set Permissions-Policy
  • SecHSTS(maxAge, includeSubdomains, preload) - configure HSTS
  • SecXSSProtection(value) - set X-XSS-Protection
  • SecAllHeaders() - convenience option that sets CSP and Permissions-Policy with restrictive defaults

CSRF middleware

Provides Cross-Site Request Forgery protection using modern browser Fetch metadata headers (Sec-Fetch-Site, Origin). For Go 1.25+, this wraps the stdlib's http.CrossOriginProtection. For earlier versions, a compatible custom implementation is used.

// basic protection
protection := rest.NewCrossOriginProtection()
router.Use(protection.Handler)

// with trusted origins for cross-origin requests
protection := rest.NewCrossOriginProtection()
if err := protection.AddTrustedOrigin("https://mobile.example.com"); err != nil {
    log.Fatal(err)
}
if err := protection.AddTrustedOrigin("https://admin.example.com"); err != nil {
    log.Fatal(err)
}
router.Use(protection.Handler)

// with bypass patterns for webhooks or OAuth
protection := rest.NewCrossOriginProtection()
protection.AddBypassPattern("/api/webhook")
protection.AddBypassPattern("/oauth/")
router.Use(protection.Handler)

// with custom deny handler
protection := rest.NewCrossOriginProtection()
protection.SetDenyHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    http.Error(w, "CSRF validation failed", http.StatusForbidden)
}))
router.Use(protection.Handler)

How it works:

  • Safe methods (GET, HEAD, OPTIONS) are always allowed
  • Checks Sec-Fetch-Site header for "same-origin" or "none"
  • Falls back to comparing Origin header with request Host
  • Requests without these headers are assumed same-origin (non-browser clients)

Available methods:

  • NewCrossOriginProtection() - creates new CSRF protection middleware
  • AddTrustedOrigin(origin) - adds origin allowed for cross-origin requests (format: "scheme://host[:port]")
  • AddBypassPattern(pattern) - adds URL pattern that bypasses protection (for webhooks, OAuth, etc.)
  • SetDenyHandler(handler) - sets custom handler for rejected requests (default: 403 Forbidden)
  • Check(request) - manually validates a request, returns error if blocked
  • Handler(handler) - wraps an http.Handler with CSRF protection

Maybe middleware

Maybe middleware allows changing the flow of the middleware stack execution depending on the return value of maybeFn(request). This is useful, for example, to skip a middleware handler if a request does not satisfy the maybeFn logic.

Reject middleware

Reject is a middleware that rejects requests with a given status code and message based on a user-defined function. This is useful, for example, to reject requests to a particular resource based on a request header, or to implement a conditional request handler based on service parameters.

example with chi router:

    router := chi.NewRouter()
	
	rejectFn := func(r *http.Request) (bool) {
        return r.Header.Get("X-Request-Id") == "" // reject if no X-Request-Id header
    }
	
	router.Use(rest.Reject(http.StatusBadRequest, "X-Request-Id header is required", rejectFn))

BasicAuth middleware family

The package provides several BasicAuth middleware implementations for different authentication needs:

BasicAuth

The base middleware that requires basic auth and matches user & passwd with a client-provided checker function.

checkFn := func(user, passwd string) bool {
    return user == "admin" && passwd == "secret"
}
router.Use(rest.BasicAuth(checkFn))
BasicAuthWithUserPasswd

A simpler version comparing user & password with provided values directly.

router.Use(rest.BasicAuthWithUserPasswd("admin", "secret"))
BasicAuthWithBcryptHash

Matches username and bcrypt-hashed password. Useful when storing hashed passwords.

hash, err := rest.GenerateBcryptHash("secret")
if err != nil {
    // handle error
}
router.Use(rest.BasicAuthWithBcryptHash("admin", hash))
BasicAuthWithArgon2Hash

Similar to bcrypt version but uses Argon2id hash with a separate salt. Both hash and salt are base64 encoded.

hash, salt, err := rest.GenerateArgon2Hash("secret")
if err != nil {
    // handle error
}
router.Use(rest.BasicAuthWithArgon2Hash("admin", hash, salt))
BasicAuthWithPrompt

Similar to BasicAuthWithUserPasswd but adds browser's authentication prompt by setting the WWW-Authenticate header.

router.Use(rest.BasicAuthWithPrompt("admin", "secret"))

All BasicAuth middlewares:

  • Return StatusUnauthorized (401) if no auth header provided
  • Return StatusForbidden (403) if credentials check failed
  • Add IsAuthorized flag to the request context, retrievable with rest.IsAuthorized(r.Context())
  • Use constant-time comparison to prevent timing attacks
  • Support secure password hashing with bcrypt and Argon2id

Benchmarks middleware

Benchmarks middleware allows measuring the time of request handling, number of requests per second and report aggregated metrics. This middleware keeps track of the request in the memory and keep up to 900 points (15 minutes, data-point per second).

To retrieve the data user should call Stats(d duration) method. The duration is the time window for which the benchmark data should be returned. It can be any duration from 1s to 15m. Note: all the time data is in microseconds.

example with chi router:

    router := chi.NewRouter()
	bench = rest.NewBenchmarks()
	router.Use(bench.Middleware)
	...
	router.Get("/bench", func(w http.ResponseWriter, r *http.Request) {
        resp := struct {
            OneMin     rest.BenchmarkStats `json:"1min"`
            FiveMin    rest.BenchmarkStats `json:"5min"`
            FifteenMin rest.BenchmarkStats `json:"15min"`
        }{
            bench.Stats(time.Minute),
            bench.Stats(time.Minute * 5),
            bench.Stats(time.Minute * 15),
        }
        render.JSON(w, r, resp) 		
    })

Helpers

  • rest.Wrap - converts a list of middlewares to nested handlers calls (in reverse order)
  • rest.JSON - map alias, just for convenience type JSON map[string]interface{}
  • rest.RenderJSON - renders json response from interface{}
  • rest.RenderJSONFromBytes - renders json response from []byte
  • rest.RenderJSONWithHTML - renders json response with html tags and forced charset=utf-8
  • rest.SendErrorJSON - makes {error: blah, details: blah} json body and responds with given error code. Also, adds context to the logged message
  • rest.NewErrorLogger - creates a struct providing shorter form of logger call
  • rest.FileServer - creates a file server for static assets with directory listing disabled
  • realip.Get - returns client's IP address
  • rest.ParseFromTo - parses "from" and "to" request's query params with various formats
  • rest.DecodeJSON - decodes request body to the provided struct
  • rest.EncodeJSON - encodes response body from the provided struct, sets Content-Type to application/json and sends the status code

Profiler

Profiler is a convenient sub-router used for mounting net/http/pprof, i.e.

 func MyService() http.Handler {
   r := chi.NewRouter()
   // ..middlewares
   r.Mount("/debug", middleware.Profiler())
   // ..routes
   return r
 }

It exposes a bunch of /pprof/* endpoints as well as /vars. Builtin support for onlyIps allows restricting access, which is important if it runs on a publicly exposed port. However, counting on IP check only is not that reliable way to limit request and for production use it would be better to add some sort of auth (for example provided BasicAuth middleware) or run with a separate http server, exposed to internal ip/port only.

Documentation

Overview

Package rest provides common middlewares and helpers for rest services

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppInfo

func AppInfo(app, author, version string) func(http.Handler) http.Handler

AppInfo adds custom app-info to the response header

func BasicAuth added in v1.5.4

func BasicAuth(checker func(user, passwd string) bool) func(http.Handler) http.Handler

BasicAuth middleware requires basic auth and matches user & passwd with client-provided checker

func BasicAuthWithArgon2Hash added in v1.20.0

func BasicAuthWithArgon2Hash(user, hashedPassword, salt string) func(http.Handler) http.Handler

BasicAuthWithArgon2Hash middleware requires basic auth and matches user & argon2 hashed password both hashedPassword and salt must be base64 encoded strings Uses Argon2id with parameters: t=1, m=64*1024 KB, p=4 threads

func BasicAuthWithBcryptHash added in v1.20.0

func BasicAuthWithBcryptHash(user, hashedPassword string) func(http.Handler) http.Handler

BasicAuthWithBcryptHash middleware requires basic auth and matches user & bcrypt hashed password

func BasicAuthWithBcryptHashAndPrompt added in v1.20.1

func BasicAuthWithBcryptHashAndPrompt(user, hashedPassword string) func(http.Handler) http.Handler

BasicAuthWithBcryptHashAndPrompt middleware requires basic auth and matches user & bcrypt hashed password If the user is not authorized, it will prompt for basic auth

func BasicAuthWithPrompt added in v1.18.0

func BasicAuthWithPrompt(user, passwd string) func(http.Handler) http.Handler

BasicAuthWithPrompt middleware requires basic auth and matches user & passwd with client-provided values If the user is not authorized, it will prompt for basic auth

func BasicAuthWithUserPasswd added in v1.17.0

func BasicAuthWithUserPasswd(user, passwd string) func(http.Handler) http.Handler

BasicAuthWithUserPasswd middleware requires basic auth and matches user & passwd with client-provided values

func BlackWords added in v1.1.0

func BlackWords(words ...string) func(http.Handler) http.Handler

BlackWords middleware doesn't allow some words in the request body

func BlackWordsFn added in v1.3.0

func BlackWordsFn(fn func() []string) func(http.Handler) http.Handler

BlackWordsFn middleware uses func to get the list and doesn't allow some words in the request body

func CORS added in v1.21.0

func CORS(opts ...CorsOpt) func(http.Handler) http.Handler

CORS is middleware that handles Cross-Origin Resource Sharing. It handles preflight OPTIONS requests and sets appropriate headers. By default allows all origins with common methods and headers.

func CacheControl added in v1.5.4

func CacheControl(expiration time.Duration, version string) func(http.Handler) http.Handler

CacheControl is a middleware setting cache expiration. Using url+version for etag

func CacheControlDynamic added in v1.5.4

func CacheControlDynamic(expiration time.Duration, versionFn func(r *http.Request) string) func(http.Handler) http.Handler

CacheControlDynamic is a middleware setting cache expiration. Using url+ func(r) for etag

func CleanPath added in v1.21.0

func CleanPath(next http.Handler) http.Handler

CleanPath middleware cleans double slashes from URL path. For example, if a request is made to /users//1 or //users////1, it will be cleaned to /users/1 before routing. Trailing slashes are preserved: /users//1/ becomes /users/1/. Dot segments (. and ..) are intentionally NOT cleaned to preserve routing semantics.

func DecodeJSON added in v1.19.0

func DecodeJSON[T any](r *http.Request, res *T) error

DecodeJSON decodes json request from http.Request to given type

func Deprecation added in v1.5.4

func Deprecation(version string, date time.Time) func(http.Handler) http.Handler

Deprecation adds a header 'Deprecation: version="version", date="date" header' see https://tools.ietf.org/id/draft-dalal-deprecation-header-00.html

func EncodeJSON added in v1.19.0

func EncodeJSON[T any](w http.ResponseWriter, status int, v T) error

EncodeJSON encodes given type to http.ResponseWriter and sets status code and content type header

func FileServer deprecated added in v1.5.4

func FileServer(public, local string, notFound io.Reader) (http.Handler, error)

FileServer is a shortcut for making FS with listing disabled and the custom noFound reader (can be nil).

Deprecated: the method is for back-compatibility only and user should use the universal NewFileServer instead

func FileServerSPA deprecated added in v1.5.4

func FileServerSPA(public, local string, notFound io.Reader) (http.Handler, error)

FileServerSPA is a shortcut for making FS with SPA-friendly handling of 404, listing disabled and the custom noFound reader (can be nil).

Deprecated: the method is for back-compatibility only and user should use the universal NewFileServer instead

func FsOptListing added in v1.5.4

func FsOptListing(fs *FS) error

FsOptListing turns on directory listing

func FsOptSPA added in v1.5.4

func FsOptSPA(fs *FS) error

FsOptSPA turns on SPA mode returning "/index.html" on not-found

func GenerateArgon2Hash added in v1.20.0

func GenerateArgon2Hash(password string) (hash, salt string, err error)

GenerateArgon2Hash generates an argon2 hash and salt from a password

func GenerateBcryptHash added in v1.20.0

func GenerateBcryptHash(password string) (string, error)

GenerateBcryptHash generates a bcrypt hash from a password

func GetTraceID added in v1.3.0

func GetTraceID(r *http.Request) string

GetTraceID returns request id from the context

func Gzip added in v1.5.4

func Gzip(contentTypes ...string) func(http.Handler) http.Handler

Gzip is a middleware compressing response

func Headers added in v1.5.4

func Headers(headers ...string) func(http.Handler) http.Handler

Headers middleware adds headers to request

func Health added in v1.16.0

func Health(path string, checkers ...func(ctx context.Context) (name string, err error)) func(http.Handler) http.Handler

Health middleware response with health info and status (200 if healthy). Stops chain if health request detected passed checkers implements custom health checks and returns error if health check failed. The check has to return name regardless to the error state. For production usage this middleware should be used with throttler and, optionally, with BasicAuth middlewares

func IsAuthorized added in v1.17.0

func IsAuthorized(ctx context.Context) bool

IsAuthorized returns true is user authorized. it can be used in handlers to check if BasicAuth middleware was applied

func Maybe added in v1.5.4

func Maybe(mw func(http.Handler) http.Handler, maybeFn func(r *http.Request) bool) func(http.Handler) http.Handler

Maybe middleware will allow you to change the flow of the middleware stack execution depending on return value of maybeFn(request). This is useful for example if you'd like to skip a middleware handler if a request does not satisfy the maybeFn logic. borrowed from https://github.com/go-chi/chi/blob/master/middleware/maybe.go

func Metrics added in v1.1.0

func Metrics(onlyIps ...string) func(http.Handler) http.Handler

Metrics responds to GET /metrics with list of expvar

func NoCache added in v1.5.4

func NoCache(h http.Handler) http.Handler

NoCache is a simple piece of middleware that sets a number of HTTP headers to prevent a router (or subrouter) from being cached by an upstream proxy and/or client.

As per http://wiki.nginx.org/HttpProxyModule - NoCache sets:

Expires: Thu, 01 Jan 1970 00:00:00 UTC
Cache-Control: no-cache, private, max-age=0
X-Accel-Expires: 0
Pragma: no-cache (for HTTP/1.0 proxies/clients)

func OnlyFrom added in v1.1.0

func OnlyFrom(onlyIps ...string) func(http.Handler) http.Handler

OnlyFrom middleware allows access for limited list of source IPs. Such IPs can be defined as complete ip (like 192.168.1.12), prefix (129.168.) or CIDR (192.168.0.0/16)

func ParseFromTo added in v1.5.4

func ParseFromTo(r *http.Request) (from, to time.Time, err error)

ParseFromTo parses from and to query params of the request

func Ping

func Ping(next http.Handler) http.Handler

Ping middleware response with pong to /ping. Stops chain if ping request detected. Handles both GET and HEAD methods - HEAD returns headers only without body, which is useful for lightweight health checks by monitoring tools.

func Profiler added in v1.5.4

func Profiler(onlyIps ...string) http.Handler

Profiler is a convenient subrouter used for mounting net/http/pprof. ie.

func MyService() http.Handler {
  r := chi.NewRouter()
  // ..middlewares
  r.Mount("/debug", middleware.Profiler())
  // ..routes
  return r
}

func RealIP added in v1.5.4

func RealIP(h http.Handler) http.Handler

RealIP is a middleware that sets a http.Request's RemoteAddr to the client's real IP. It checks headers in the following priority order:

  1. X-Real-IP - trusted proxy (nginx/reproxy) sets this to actual client
  2. CF-Connecting-IP - Cloudflare's header for original client
  3. X-Forwarded-For - leftmost public IP (original client in CDN/proxy chain)
  4. RemoteAddr - fallback for direct connections

Only public IPs are accepted from headers; private/loopback/link-local IPs are skipped.

This middleware should only be used if user can trust the headers sent with request. If reverse proxies are configured to pass along arbitrary header values from the client, or if this middleware used without a reverse proxy, malicious clients could set anything as these headers and spoof their IP address.

func Recoverer

func Recoverer(l logger.Backend) func(http.Handler) http.Handler

Recoverer is a middleware that recovers from panics, logs the panic and returns a HTTP 500 status if possible.

func Reject added in v1.16.0

func Reject(errCode int, errMsg string, rejectFn func(r *http.Request) bool) func(h http.Handler) http.Handler

Reject is a middleware that conditionally rejects requests with a given status code and message. user-defined condition function rejectFn is used to determine if the request should be rejected.

func RenderJSON added in v1.1.0

func RenderJSON(w http.ResponseWriter, data any)

RenderJSON sends data as json

func RenderJSONFromBytes

func RenderJSONFromBytes(w http.ResponseWriter, r *http.Request, data []byte) error

RenderJSONFromBytes sends binary data as json

func RenderJSONWithHTML

func RenderJSONWithHTML(w http.ResponseWriter, r *http.Request, v any) error

RenderJSONWithHTML allows html tags and forces charset=utf-8

func Rewrite added in v1.5.4

func Rewrite(from, to string) func(http.Handler) http.Handler

Rewrite middleware with from->to rule. Supports regex (like nginx) and prevents multiple rewrites example: Rewrite(`^/sites/(.*)/settings/$`, `/sites/settings/$1`

func Secure added in v1.21.0

func Secure(opts ...SecOpt) func(http.Handler) http.Handler

Secure is middleware that adds security headers to responses. By default it sets: X-Frame-Options, X-Content-Type-Options, Referrer-Policy, X-XSS-Protection, and Strict-Transport-Security (for HTTPS only). Use SecOpt functions to customize the configuration.

func SendErrorJSON

func SendErrorJSON(w http.ResponseWriter, r *http.Request, l logger.Backend, code int, err error, msg string)

SendErrorJSON sends {error: msg} with error code and logging error and caller

func SizeLimit added in v1.4.0

func SizeLimit(size int64) func(http.Handler) http.Handler

SizeLimit middleware checks if body size is above the limit and returns StatusRequestEntityTooLarge (413)

func StripSlashes added in v1.21.0

func StripSlashes(next http.Handler) http.Handler

StripSlashes middleware removes trailing slashes from URL path. For example, /users/1/ becomes /users/1. The root path "/" is preserved.

func Throttle added in v1.5.4

func Throttle(limit int64) func(http.Handler) http.Handler

Throttle middleware checks how many request in-fly and rejects with 503 if exceeded

func Trace added in v1.3.0

func Trace(next http.Handler) http.Handler

Trace looks for header X-Request-ID and makes it as random id if not found, then populates it to the result's header and to request context

func Wrap added in v1.5.4

func Wrap(handler http.Handler, mws ...func(http.Handler) http.Handler) http.Handler

Wrap converts a list of middlewares to nested calls (in reverse order)

Types

type BenchmarkStats added in v1.5.4

type BenchmarkStats struct {
	Requests        int     `json:"requests"`
	RequestsSec     float64 `json:"requests_sec"`
	AverageRespTime int64   `json:"average_resp_time"`
	MinRespTime     int64   `json:"min_resp_time"`
	MaxRespTime     int64   `json:"max_resp_time"`
}

BenchmarkStats holds the stats for a given interval

type Benchmarks added in v1.5.4

type Benchmarks struct {
	// contains filtered or unexported fields
}

Benchmarks is a basic benchmarking middleware collecting and reporting performance metrics It keeps track of the requests speeds and counts in 1s benchData buckets ,limiting the number of buckets to maxTimeRange. User can request the benchmark for any time duration. This is intended to be used for retrieving the benchmark data for the last minute, 5 minutes and up to maxTimeRange.

func NewBenchmarks added in v1.5.4

func NewBenchmarks() *Benchmarks

NewBenchmarks creates a new benchmark middleware

func (*Benchmarks) Handler added in v1.5.4

func (b *Benchmarks) Handler(next http.Handler) http.Handler

Handler calculates 1/5/10m request per second and allows to access those values

func (*Benchmarks) Stats added in v1.5.4

func (b *Benchmarks) Stats(interval time.Duration) BenchmarkStats

Stats returns the current benchmark stats for the given duration

func (*Benchmarks) WithTimeRange added in v1.15.6

func (b *Benchmarks) WithTimeRange(maximum time.Duration) *Benchmarks

WithTimeRange sets the maximum time range for the benchmark to keep data for. Default is 15 minutes. The increase of this range will change memory utilization as each second of the range kept as benchData aggregate. The default means 15*60 = 900 seconds of data aggregate. Larger range allows for longer time periods to be benchmarked.

type CORSConfig added in v1.21.0

type CORSConfig struct {
	// AllowedOrigins is a list of origins that may access the resource.
	// use "*" to allow all origins (not recommended with credentials).
	// default: ["*"]
	AllowedOrigins []string
	// AllowedMethods is a list of methods the client is allowed to use.
	// default: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
	AllowedMethods []string
	// AllowedHeaders is a list of headers the client is allowed to send.
	// default: Accept, Content-Type, Authorization, X-Requested-With
	AllowedHeaders []string
	// ExposedHeaders is a list of headers that are safe to expose to the client.
	// default: empty
	ExposedHeaders []string
	// AllowCredentials indicates whether the request can include credentials.
	// when true, AllowedOrigins cannot be "*" (browser security restriction).
	// default: false
	AllowCredentials bool
	// MaxAge indicates how long (in seconds) the results of a preflight can be cached.
	// default: 0 (no caching)
	MaxAge int
}

CORSConfig defines CORS middleware configuration. Use CorsOpt functions to customize.

type CorsOpt added in v1.21.0

type CorsOpt func(*CORSConfig)

CorsOpt is a functional option for CORSConfig

func CorsAllowCredentials added in v1.21.0

func CorsAllowCredentials(allow bool) CorsOpt

CorsAllowCredentials enables or disables credentials. When true, AllowedOrigins cannot be "*".

func CorsAllowedHeaders added in v1.21.0

func CorsAllowedHeaders(headers ...string) CorsOpt

CorsAllowedHeaders sets the list of allowed request headers.

func CorsAllowedMethods added in v1.21.0

func CorsAllowedMethods(methods ...string) CorsOpt

CorsAllowedMethods sets the list of allowed HTTP methods.

func CorsAllowedOrigins added in v1.21.0

func CorsAllowedOrigins(origins ...string) CorsOpt

CorsAllowedOrigins sets the list of allowed origins. Use "*" to allow all origins (not recommended with credentials).

func CorsExposedHeaders added in v1.21.0

func CorsExposedHeaders(headers ...string) CorsOpt

CorsExposedHeaders sets the list of headers exposed to the client.

func CorsMaxAge added in v1.21.0

func CorsMaxAge(seconds int) CorsOpt

CorsMaxAge sets how long (in seconds) preflight results can be cached.

type CrossOriginProtection added in v1.21.0

type CrossOriginProtection struct {
	// contains filtered or unexported fields
}

CrossOriginProtection provides CSRF protection using modern browser Fetch metadata. It validates requests using Sec-Fetch-Site and Origin headers, rejecting cross-origin state-changing requests. Safe methods (GET, HEAD, OPTIONS) are always allowed.

For Go 1.25+, this wraps the stdlib http.CrossOriginProtection. For earlier versions, it provides an equivalent custom implementation.

func NewCrossOriginProtection added in v1.21.0

func NewCrossOriginProtection() *CrossOriginProtection

NewCrossOriginProtection creates a new CSRF protection middleware.

func (*CrossOriginProtection) AddBypassPattern added in v1.21.0

func (c *CrossOriginProtection) AddBypassPattern(pattern string)

AddBypassPattern adds a URL pattern that should bypass CSRF protection. Patterns follow the same syntax as http.ServeMux (e.g., "/api/webhook", "/oauth/"). Use sparingly and only for endpoints that have alternative authentication.

func (*CrossOriginProtection) AddTrustedOrigin added in v1.21.0

func (c *CrossOriginProtection) AddTrustedOrigin(origin string) error

AddTrustedOrigin adds an origin that should be allowed to make cross-origin requests. The origin must be in the format "scheme://host" or "scheme://host:port". Returns an error if the origin format is invalid.

func (*CrossOriginProtection) Check added in v1.21.0

func (c *CrossOriginProtection) Check(r *http.Request) error

Check validates a request against CSRF protection rules. Returns nil if the request is allowed, or an error describing why it was rejected.

func (*CrossOriginProtection) Handler added in v1.21.0

Handler wraps an http.Handler with CSRF protection. Rejected requests receive a 403 Forbidden response (or custom deny handler).

func (*CrossOriginProtection) SetDenyHandler added in v1.21.0

func (c *CrossOriginProtection) SetDenyHandler(h http.Handler)

SetDenyHandler sets a custom handler for rejected requests. If not set, rejected requests receive a 403 Forbidden response.

type ErrorLogger added in v1.5.0

type ErrorLogger struct {
	// contains filtered or unexported fields
}

ErrorLogger wraps logger.Backend

func NewErrorLogger added in v1.5.0

func NewErrorLogger(l logger.Backend) *ErrorLogger

NewErrorLogger creates ErrorLogger for given Backend

func (*ErrorLogger) Log added in v1.5.0

func (e *ErrorLogger) Log(w http.ResponseWriter, r *http.Request, httpCode int, err error, msg ...string)

Log sends json error message {error: msg} with error code and logging error and caller

type FS added in v1.5.4

type FS struct {
	// contains filtered or unexported fields
}

FS provides http.FileServer handler to serve static files from a http.FileSystem, prevents directory listing by default and supports spa-friendly mode (off by default) returning /index.html on 404. - public defines base path of the url, i.e. for http://example.com/static/* it should be /static - local for the local path to the root of the served directory - notFound is the reader for the custom 404 html, can be nil for default

func NewFileServer added in v1.5.4

func NewFileServer(public, local string, options ...FsOpt) (*FS, error)

NewFileServer creates file server with optional spa mode and optional direcroty listing (disabled by default)

func (*FS) ServeHTTP added in v1.5.4

func (fs *FS) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP makes FileServer compatible with http.Handler interface

type FsOpt added in v1.5.4

type FsOpt func(fs *FS) error

FsOpt defines functional option type

func FsOptCustom404 added in v1.5.4

func FsOptCustom404(fr io.Reader) FsOpt

FsOptCustom404 sets custom 404 reader

type JSON

type JSON map[string]any

JSON is a map alias, just for convenience

type SecOpt added in v1.21.0

type SecOpt func(*SecureConfig)

SecOpt is a functional option for SecureConfig

func SecAllHeaders added in v1.21.0

func SecAllHeaders() SecOpt

SecAllHeaders is a convenience option to set common headers for secure web applications. Sets CSP with self-only policy and restrictive permissions.

func SecContentSecurityPolicy added in v1.21.0

func SecContentSecurityPolicy(policy string) SecOpt

SecContentSecurityPolicy sets Content-Security-Policy header. Example: "default-src 'self'; script-src 'self'"

func SecContentTypeNosniff added in v1.21.0

func SecContentTypeNosniff(enable bool) SecOpt

SecContentTypeNosniff enables or disables X-Content-Type-Options: nosniff

func SecFrameOptions added in v1.21.0

func SecFrameOptions(value string) SecOpt

SecFrameOptions sets X-Frame-Options header. Common values: "DENY", "SAMEORIGIN"

func SecHSTS added in v1.21.0

func SecHSTS(maxAge int, includeSubdomains, preload bool) SecOpt

SecHSTS configures Strict-Transport-Security header. maxAge is in seconds (0 disables HSTS), includeSubdomains and preload are optional flags. Note: HSTS header is only sent when the request is over HTTPS.

func SecPermissionsPolicy added in v1.21.0

func SecPermissionsPolicy(policy string) SecOpt

SecPermissionsPolicy sets Permissions-Policy header. Example: "geolocation=(), microphone=()"

func SecReferrerPolicy added in v1.21.0

func SecReferrerPolicy(policy string) SecOpt

SecReferrerPolicy sets Referrer-Policy header. Common values: "no-referrer", "same-origin", "strict-origin", "strict-origin-when-cross-origin"

func SecXSSProtection added in v1.21.0

func SecXSSProtection(value string) SecOpt

SecXSSProtection sets X-XSS-Protection header. Set to empty string to disable. Common values: "0", "1", "1; mode=block"

type SecureConfig added in v1.21.0

type SecureConfig struct {
	// xFrameOptions sets X-Frame-Options header. Default: DENY
	XFrameOptions string
	// xContentTypeOptions sets X-Content-Type-Options. Default: nosniff
	XContentTypeOptions string
	// ReferrerPolicy sets Referrer-Policy header. Default: strict-origin-when-cross-origin
	ReferrerPolicy string
	// ContentSecurityPolicy sets Content-Security-Policy header. Default: empty (not set)
	ContentSecurityPolicy string
	// PermissionsPolicy sets Permissions-Policy header. Default: empty (not set)
	PermissionsPolicy string
	// sTSSeconds sets max-age for Strict-Transport-Security. 0 disables.
	// only sent when request uses HTTPS. Default: 31536000 (1 year)
	STSSeconds int
	// sTSIncludeSubdomains adds includeSubDomains to HSTS. Default: true
	STSIncludeSubdomains bool
	// sTSPreload adds preload flag to HSTS. Default: false
	STSPreload bool
	// xSSProtection sets X-XSS-Protection header. Default: 1; mode=block
	// note: this header is deprecated in modern browsers but still useful for older ones
	XSSProtection string
}

SecureConfig defines security headers configuration. Use SecOpt functions to customize.

Directories

Path Synopsis
Package logger implements logging middleware
Package logger implements logging middleware
Package realip extracts a real IP address from the request.
Package realip extracts a real IP address from the request.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL