Skip to main content

Overview

The bodyclose middleware ensures request bodies are properly closed after processing, preventing resource leaks. Use it when you need:
  • Prevent connection leaks
  • Ensure proper resource cleanup
  • Handle abandoned requests

Installation

import "github.com/go-mizu/mizu/middlewares/bodyclose"

Quick Start

app := mizu.New()

// Auto-close request bodies
app.Use(bodyclose.New())

Examples

Basic Usage

app.Use(bodyclose.New())

With Drain

// Drain body before closing (for keep-alive)
app.Use(bodyclose.WithDrain())

API Reference

Functions

// New creates body close middleware with default options
func New() mizu.Middleware

// WithOptions creates bodyclose middleware with custom options
func WithOptions(opts Options) mizu.Middleware

// Drain creates middleware that drains request bodies
func Drain() mizu.Middleware

// NoDrain creates middleware that closes without draining
func NoDrain() mizu.Middleware

Options

type Options struct {
    // DrainBody drains the body before closing.
    // Default: true.
    DrainBody bool

    // MaxDrain is the maximum bytes to drain.
    // Default: 8KB.
    MaxDrain int64
}

Technical Details

The bodyclose middleware operates by wrapping the request handler with a deferred cleanup function that ensures proper resource management:

Implementation Strategy

  1. Nil Body Check: Immediately passes control to the next handler if the request body is nil, avoiding unnecessary overhead
  2. Deferred Cleanup: Uses Go’s defer statement to guarantee body cleanup regardless of handler outcome (success, error, or panic)
  3. Optional Draining: When DrainBody is enabled, reads and discards up to MaxDrain bytes before closing to enable HTTP keep-alive connection reuse
  4. Connection Reuse: By draining the body, the middleware signals to the HTTP client that the connection can be safely reused in connection pools

Resource Management

  • Default MaxDrain: 8KB (8192 bytes) to balance connection reuse benefits with performance
  • Drain Mechanism: Uses io.CopyN to limit the amount of data drained, preventing excessive memory consumption on large bodies
  • Error Handling: Silently ignores drain and close errors to prevent interference with the main request flow

Performance Characteristics

  • Minimal Overhead: Only adds a single function call and defer statement per request
  • Memory Efficient: Draining is capped by MaxDrain to prevent memory exhaustion
  • No Blocking: Draining respects the MaxDrain limit and doesn’t attempt to fully read unbounded bodies

Why It Matters

Without proper body closing:
  • Connections may not be reused
  • Memory leaks can occur
  • Connection pool exhaustion

Best Practices

  • Place early in middleware chain
  • Use with connection pooling
  • Consider draining for HTTP keep-alive

Testing

The bodyclose middleware includes comprehensive test coverage to ensure proper functionality:
Test CaseDescriptionExpected Behavior
TestNewBasic middleware creation with default optionsRequest body is properly handled, returns HTTP 200 OK
TestWithOptions_DrainBodyMiddleware with DrainBody enabledBody is closed after being drained, tracking confirms closure
TestWithOptions_NoDrainMiddleware with DrainBody disabledBody is closed without draining, tracking confirms closure
TestNilBodyRequest with nil body (GET request)Middleware handles nil body gracefully, returns HTTP 200 OK
TestDrainUsing the Drain() convenience functionBody is drained before closing, request completes successfully
TestNoDrainUsing the NoDrain() convenience functionBody is closed without draining, request completes successfully
TestWithOptions_MaxDrainCustom MaxDrain limit (10 bytes on 1000-byte body)Only drains up to MaxDrain bytes, prevents excessive memory usage

Test Coverage

The test suite uses a custom trackingBody type that monitors:
  • Whether the body was closed (closed field)
  • Whether the body was fully drained (drained field)
This ensures that the middleware behaves correctly in various scenarios including unread bodies, partial reads, and different configuration options.