middleware

package module
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Mar 21, 2026 License: MIT Imports: 15 Imported by: 0

README

go-middleware

CI Go Reference License

Composable HTTP middleware collection for Go's net/http. No framework required

Installation

go get github.com/philiprehberger/go-middleware

Usage

package main

import (
	"log/slog"
	"net/http"
	"os"
	"time"

	mw "github.com/philiprehberger/go-middleware"
)

func main() {
	logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

	stack := mw.Chain(
		mw.RequestID,
		mw.Logger(logger),
		mw.Recover(),
		mw.CORS(),
		mw.SecureHeaders(),
		mw.BearerAuth(func(token string) error { return nil }),
		mw.Timeout(10*time.Second),
		mw.Compress(),
		mw.ETag(),
		mw.Metrics(func(method, path string, status int, duration time.Duration) {
			logger.Info("metrics", "method", method, "path", path, "status", status, "duration", duration)
		}),
	)

	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	http.ListenAndServe(":8080", stack(mux))
}
Available Middleware

Chain — Compose multiple middleware into a single wrapper.

handler := mw.Chain(m1, m2, m3)(finalHandler)

Logger — Log each request with method, path, status, and duration.

mw.Logger(slog.Default())

Recover — Catch panics and return 500 Internal Server Error.

mw.Recover()

CORS — Handle Cross-Origin Resource Sharing with functional options.

mw.CORS(
    mw.AllowOrigins("https://example.com"),
    mw.AllowMethods("GET", "POST"),
    mw.AllowHeaders("Authorization"),
    mw.AllowCredentials(),
    mw.MaxAge(3600),
)

SecureHeaders — Set common security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy, X-XSS-Protection).

mw.SecureHeaders()

Timeout — Enforce a request timeout, returning 503 if exceeded.

mw.Timeout(10 * time.Second)

Compress — Gzip-compress responses when the client supports it.

mw.Compress()

ETag — Generate ETag headers and return 304 Not Modified when appropriate.

mw.ETag()

Request ID — Generate or propagate an X-Request-ID header. If the incoming request already has one, it is preserved; otherwise a new random ID is generated. The ID is also stored in the request context.

mw.RequestID
// Extract from context inside a handler:
id := mw.RequestIDFromContext(r.Context())

Bearer Auth — Validate Authorization: Bearer <token> headers using a custom validation function. Returns 401 if missing or invalid.

mw.BearerAuth(func(token string) error {
    if token != "expected" {
        return errors.New("invalid token")
    }
    return nil
})

Metrics — Call a function after each request with method, path, status code, and duration.

mw.Metrics(func(method, path string, status int, duration time.Duration) {
    log.Printf("%s %s -> %d (%s)", method, path, status, duration)
})
Middleware Ordering
import mw "github.com/philiprehberger/go-middleware"

// Recommended order: recovery → logging → security → business logic
handler := mw.Chain(
    mw.Recover(),
    mw.RequestID,
    mw.Logger(slog.Default()),
    mw.CORS(mw.AllowOrigins("*")),
    mw.BearerAuth(validateToken),
)(yourHandler)
Preset Chains
import mw "github.com/philiprehberger/go-middleware"

// Common API preset
apiChain := mw.Chain(
    mw.Recover(),
    mw.RequestID,
    mw.Logger(slog.Default()),
    mw.Timeout(30 * time.Second),
    mw.CORS(mw.AllowOrigins("*")),
)
http.Handle("/api/", apiChain(apiHandler))

API

Function Signature Description
Chain Chain(middlewares ...Middleware) Middleware Compose middleware in order
Logger Logger(logger *slog.Logger) Middleware Request logging
Recover Recover() Middleware Panic recovery
CORS CORS(opts ...CORSOption) Middleware CORS handling
AllowOrigins AllowOrigins(origins ...string) CORSOption Set allowed origins
AllowMethods AllowMethods(methods ...string) CORSOption Set allowed methods
AllowHeaders AllowHeaders(headers ...string) CORSOption Set allowed headers
AllowCredentials AllowCredentials() CORSOption Enable credentials
MaxAge MaxAge(seconds int) CORSOption Set preflight cache duration
SecureHeaders SecureHeaders() Middleware Security headers
Timeout Timeout(d time.Duration) Middleware Request timeout
Compress Compress() Middleware Gzip compression
ETag ETag() Middleware ETag generation
RequestID RequestID(next http.Handler) http.Handler Request ID generation/propagation
RequestIDFromContext RequestIDFromContext(ctx context.Context) string Extract request ID from context
BearerAuth BearerAuth(validate func(string) error) func(http.Handler) http.Handler Bearer token authentication
Metrics Metrics(onRequest func(string, string, int, time.Duration)) func(http.Handler) http.Handler Request metrics collection

Development

go test ./...
go vet ./...

License

MIT

Documentation

Overview

Package middleware provides composable HTTP middleware for net/http.

Middleware functions wrap http.Handler to add cross-cutting concerns like logging, panic recovery, CORS, security headers, timeouts, compression, and ETag generation. Use Chain to compose multiple middleware together.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BearerAuth added in v0.2.0

func BearerAuth(validate func(token string) error) func(http.Handler) http.Handler

BearerAuth validates the Authorization: Bearer <token> header using the provided validate function. If valid, the request is passed downstream. If invalid, responds with 401 Unauthorized.

func Metrics added in v0.2.0

func Metrics(onRequest func(method, path string, status int, duration time.Duration)) func(http.Handler) http.Handler

Metrics calls onRequest after each request with method, path, status code, and duration.

func RequestID added in v0.2.0

func RequestID(next http.Handler) http.Handler

RequestID generates or propagates an X-Request-ID header. If the incoming request has X-Request-ID, it's preserved. Otherwise a new one is generated.

func RequestIDFromContext added in v0.2.0

func RequestIDFromContext(ctx context.Context) string

RequestIDFromContext extracts the request ID from the context.

Types

type CORSOption

type CORSOption func(*corsConfig)

CORSOption configures the CORS middleware.

func AllowCredentials

func AllowCredentials() CORSOption

AllowCredentials enables the Access-Control-Allow-Credentials header.

func AllowHeaders

func AllowHeaders(headers ...string) CORSOption

AllowHeaders sets the allowed request headers for CORS requests.

func AllowMethods

func AllowMethods(methods ...string) CORSOption

AllowMethods sets the allowed HTTP methods for CORS requests.

func AllowOrigins

func AllowOrigins(origins ...string) CORSOption

AllowOrigins sets the allowed origins. An empty list or a list containing "*" allows all origins.

func MaxAge

func MaxAge(seconds int) CORSOption

MaxAge sets the maximum time (in seconds) that preflight results can be cached.

type Middleware

type Middleware = func(http.Handler) http.Handler

Middleware is a function that wraps an http.Handler to add behavior.

func CORS

func CORS(opts ...CORSOption) Middleware

CORS returns middleware that handles Cross-Origin Resource Sharing. By default it allows all origins and the methods GET, POST, HEAD, PUT, DELETE, PATCH.

func Chain

func Chain(middlewares ...Middleware) Middleware

Chain composes multiple middleware into a single Middleware. Middleware are applied in the order given: the first middleware in the list wraps the outermost layer, so it executes first on the way in and last on the way out.

func Compress

func Compress() Middleware

Compress returns middleware that gzip-compresses response bodies when the client indicates support via the Accept-Encoding header. Responses with content types that are already compressed (e.g., images) are skipped.

func ETag

func ETag() Middleware

ETag returns middleware that generates an ETag header based on a SHA-256 hash of the response body. If the request includes an If-None-Match header that matches the computed ETag, a 304 Not Modified response is returned instead.

func Logger

func Logger(logger *slog.Logger) Middleware

Logger returns middleware that logs each request using the provided slog.Logger. It records the HTTP method, path, response status code, and request duration.

func Recover

func Recover() Middleware

Recover returns middleware that recovers from panics in downstream handlers. When a panic occurs, it logs the panic value and stack trace to stderr and responds with a 500 Internal Server Error.

func SecureHeaders

func SecureHeaders() Middleware

SecureHeaders returns middleware that sets common security-related HTTP headers. It sets:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Referrer-Policy: strict-origin-when-cross-origin
  • X-XSS-Protection: 0

func Timeout

func Timeout(d time.Duration) Middleware

Timeout returns middleware that enforces a timeout on each request. If the handler does not complete within the given duration, the client receives a 503 Service Unavailable response.

Jump to

Keyboard shortcuts

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