// NOTE: This middleware is not needed for most applications. // Browsers and typical HTTP clients do not compress request bodies, // so decompressing requests is unnecessary unless you explicitly expect // gzip-compressed payloads from known clients. package middleware import ( "compress/gzip" "io" "net/http" "strings" ) // DecompressOptions configures the decompression middleware type DecompressOptions struct { // MaxSize is the maximum size of the decompressed body in bytes // Zero means no limit MaxSize int64 } // DefaultDecompressOptions provides sensible default options func DefaultDecompressOptions() *DecompressOptions { return &DecompressOptions{ MaxSize: 10 << 20, // 10MB } } // Decompress creates a middleware that decompresses HTTP requests with gzip content encoding func Decompress(opts *DecompressOptions) Middleware { // Use default options if none provided if opts == nil { opts = DefaultDecompressOptions() } return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Check if the request has Content-Encoding header contentEncoding := r.Header.Get("Content-Encoding") // If not compressed, pass through if contentEncoding == "" { next.ServeHTTP(w, r) return } // Check if gzip encoded if strings.Contains(contentEncoding, "gzip") { // Create a gzip reader gz, err := gzip.NewReader(r.Body) if err != nil { http.Error(w, "Invalid gzip body", http.StatusBadRequest) return } defer gz.Close() // Add limit reader if max size is specified var bodyReader io.Reader = gz if opts.MaxSize > 0 { bodyReader = io.LimitReader(gz, opts.MaxSize) } // Replace the body with a decompressed reader r.Body = io.NopCloser(bodyReader) // Remove the content-encoding header to signal that the body is now decompressed r.Header.Del("Content-Encoding") // Adjust content length because the body has been decompressed r.Header.Del("Content-Length") } // Call the next handler with the decompressed body next.ServeHTTP(w, r) }) } } // DecompressDefault creates a middleware that decompresses HTTP requests with default options func DecompressDefault() Middleware { return Decompress(nil) }