middlewares

package module
v0.0.0-...-ad3e8ca Latest Latest
Warning

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

Go to latest
Published: Apr 9, 2025 License: MIT Imports: 21 Imported by: 6

README

Go HTTP Middlewares

MIT License Go Version

A collection of high-performance HTTP middlewares for Go web applications. These middlewares are designed to be composable and to work seamlessly with the standard http.Handler interface.

Installation

go get github.com/casualjim/middlewares

Available Middlewares

Compression
  • CompressHandler / CompressHandlerLevel: Compresses HTTP responses using gzip or deflate based on the client's Accept-Encoding header.
Error Handling
  • RecoverRendered / Recover: Catches panics in HTTP handlers and returns an appropriate error response.
  • Error: Helper functions for working with HTTP errors.
Content Negotiation
  • RequireJSONBody: Validates that the request body contains valid JSON.
  • AllowMethods: Restricts requests to specific HTTP methods.
Response Helpers
  • JSON: Helper for writing JSON responses.
  • JSONError: Helper for writing JSON error responses.
Logging
  • LoggingTransport: Logs HTTP client requests and responses.
  • DebugDumpMiddleware: Logs detailed HTTP server requests and responses.
Caching Control
  • NoCache: Prevents caching of HTTP responses.
Profiling
  • NewProfiler: Exposes the Go profiling endpoints at /debug/pprof/.
Proxy Support
  • ProxyHeaders: Properly handles headers set by reverse proxies.

Usage Examples

Basic Usage
package main

import (
    "log/slog"
    "net/http"
    
    "github.com/casualjim/middlewares"
    "github.com/justinas/alice"
)

func main() {
    logger := slog.Default()
    
    // Create a middleware chain
    chain := alice.New(
        middlewares.Recover(logger),
        middlewares.CompressHandler,
        middlewares.NoCache,
        middlewares.ProxyHeaders,
    )
    
    // Your handler
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Respond with JSON
        middlewares.JSON(w, map[string]string{"message": "Hello, World!"})
    })
    
    // Use the middleware chain with your handler
    http.Handle("/", chain.Then(handler))
    http.ListenAndServe(":8080", nil)
}
Error Handling and JSON Responses
func handleRequest(w http.ResponseWriter, r *http.Request) {
    // Validate that the request body is JSON
    body, err := middlewares.RequireJSONBody(w, r)
    if err != nil {
        middlewares.JSONError(w, err.Error(), http.StatusBadRequest)
        return
    }
    
    // Process the body...
    
    // Respond with a successful JSON response
    middlewares.JSON(w, map[string]string{"status": "success"}, http.StatusOK)
}
Method Restrictions
func handler(w http.ResponseWriter, r *http.Request) {
    // Only allow GET and POST requests
    if err := middlewares.AllowMethods([]string{"GET", "POST"}, w, r); err != nil {
        return // AllowMethods already sets the appropriate response status and headers
    }
    
    // Continue processing...
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	ContentTypeJSON string = "application/json"
	// https://github.com/ietf-wg-httpapi/mediatypes/blob/main/draft-ietf-httpapi-yaml-mediatypes.md
	ContentTypeYAML string = "application/yaml"
)

Variables

This section is empty.

Functions

func AllowMethods

func AllowMethods(methods []string, rw http.ResponseWriter, r *http.Request) error

func AlwaysDumpRequestBody

func AlwaysDumpRequestBody() func(*loggingTransport)

func AlwaysDumpResponseBody

func AlwaysDumpResponseBody() func(*loggingTransport)

func CompressHandler

func CompressHandler(h http.Handler) http.Handler

CompressHandler gzip compresses HTTP responses for clients that support it via the 'Accept-Encoding' header.

Compressing TLS traffic may leak the page contents to an attacker if the page contains user input: http://security.stackexchange.com/a/102015/12208

func CompressHandlerLevel

func CompressHandlerLevel(h http.Handler, level int) http.Handler

CompressHandlerLevel gzip compresses HTTP responses with specified compression level for clients that support it via the 'Accept-Encoding' header.

The compression level should be gzip.DefaultCompression, gzip.NoCompression, or any integer value between gzip.BestSpeed and gzip.BestCompression inclusive. gzip.DefaultCompression is used in case of invalid compression level.

func DebugDumpMiddleware

func DebugDumpMiddleware(next http.Handler) http.Handler

DebugDumpMiddleware that logs the request and responses.

func ErrBody

func ErrBody(e error) string

func ErrStatusCode

func ErrStatusCode(e error) int

func Error

func Error(statusCode int, body string) error

func FilteredDumpRequestBody

func FilteredDumpRequestBody(filter func(*http.Request) bool) func(*loggingTransport)

func FilteredDumpResponseBody

func FilteredDumpResponseBody(filter func(*http.Request, *http.Response) bool) func(*loggingTransport)

func IsBadRequest

func IsBadRequest(e error) bool

func IsError

func IsError(e error, code int) bool

func IsForbidden

func IsForbidden(e error) bool

func IsNotFound

func IsNotFound(e error) bool

func IsServerError

func IsServerError(e error) bool

func IsUnauthorized

func IsUnauthorized(e error) bool

func JSON

func JSON[T any](w http.ResponseWriter, data T, code ...int)

func JSONError

func JSONError(w http.ResponseWriter, error string, code int, headers ...http.Header)

func LoggingTransport

func LoggingTransport(toWrap http.RoundTripper, opts ...func(*loggingTransport)) http.RoundTripper

LoggingTransport decorates an existing transport with logging of request and responses

func LoggingTransportDebug

func LoggingTransportDebug(toWrap http.RoundTripper, opts ...func(*loggingTransport)) http.RoundTripper

func NeverDumpRequestBody

func NeverDumpRequestBody() func(*loggingTransport)

func NeverDumpResponseBody

func NeverDumpResponseBody() func(*loggingTransport)

func NewProfiler

func NewProfiler(next http.Handler) http.Handler

NewProfiler creates a middleware for profiling

func NoCache

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 ProxyHeaders

func ProxyHeaders(h http.Handler) http.Handler

ProxyHeaders inspects common reverse proxy headers and sets the corresponding fields in the HTTP request struct. These are X-Forwarded-For and X-Real-IP for the remote (client) IP address, X-Forwarded-Proto or X-Forwarded-Scheme for the scheme (http|https) and the RFC7239 Forwarded header, which may include both client IPs and schemes.

NOTE: This middleware should only be used when behind a reverse proxy like nginx, HAProxy or Apache. Reverse proxies that don't (or are configured not to) strip these headers from client requests, or where these headers are accepted "as is" from a remote client (e.g. when Go is not behind a proxy), can manifest as a vulnerability if your application uses these headers for validating the 'trustworthiness' of a request.

func Recover

func Recover(lg *slog.Logger) func(http.Handler) http.Handler

func RecoverRendered

func RecoverRendered(lg *slog.Logger, renderPanic PanicRenderer) func(http.Handler) http.Handler

func RequireJSONBody

func RequireJSONBody(rw http.ResponseWriter, r *http.Request) ([]byte, error)

Types

type PanicRenderer

type PanicRenderer func(http.ResponseWriter, string, int, ...http.Header)

type Profiler

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

Profiler exposes net/http/pprof as a middleware

func (*Profiler) ServeHTTP

func (p *Profiler) ServeHTTP(rw http.ResponseWriter, r *http.Request)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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