liveBook · Manning

Middleware

As explained in Go by Example

Middleware is a software pattern in which a component wraps a handler or processing component to add behavior before, after, or around the wrapped component's execution.

Middleware wraps an HTTP handler with behavior that runs before, after, or around the handler without changing the handler itself. Requests flow inward through wrapper layers; responses return outward through those layers. The common Go shape is func(http.Handler) http.Handler, which makes independently written wrappers chainable. section 9.1.1 section 9.0

Figure 9.1 Middleware layers process both incoming HTTP requests and outgoing HTTP responses, enhancing functionality without altering the handler code.
A diagram of a software server

AI-generated content may be incorrect.

Use the layer diagram to trace the two-way flow: middleware receives a request before the handler and can act again as the response returns. section 9.1.1

A wrapper returns an http.Handler whose ServeHTTP method calls next.ServeHTTP at the chosen point. Work before that call can preprocess a request; work after it can log, measure, or record results. Applying wrappers as MiddlewareA(MiddlewareB(handler)) puts A first on the request path and last on the response path. section 9.1.1 section 9.2.2

Log every API request once

Wrap a ServeMux at server setup rather than inserting logging into each route handler. A logger-injected middleware calls the next handler, then records the request path and method. Injecting *slog.Logger keeps configuration with the caller and avoids the testing and flexibility costs of a global logger. section 9.1.2 section 9.1.5

Small middleware can each own one concern. Duration records elapsed handler time with defer; StatusCode replaces the ResponseWriter with an interceptor that observes WriteHeader. RecordResponse chains such wrappers around a handler and returns collected metrics for logging. Pointer-backed metric storage must be newly allocated per request, or concurrent requests can race. section 9.2.1 section 9.2.2 section 9.3.2

Design middleware for reuse and safe composition:

  • Preserve the func(http.Handler) http.Handler signature so wrappers can chain with local or third-party middleware. section 9.1.2
  • Keep each wrapper focused, such as measuring duration or capturing status, and use helpers only when a bundled operation is convenient. section 9.2 section 9.2.2
  • Use Context values for peripheral request-scoped information such as trace IDs, not to control program flow. section 9.5.2

Propagate a trace ID

A trace-ID middleware checks Request.Context, adds a generated ID only when absent, clones the request with that Context, and passes it downstream. Handlers, other middleware, and logging can then associate entries from the same request without changing their APIs. section 9.5 section 9.5.2

Wrapping adds behavior while leaving existing handlers untouched, reducing coupling and making features easier to add or remove. Middleware is one expression of composition: combine focused interface-based pieces instead of expanding a large, tightly coupled handler or manager. section 9.1.5 section 9.11

How Go by Example covers it

How deep it goes
Builds logger, duration, status-code, and trace-ID wrappers, including chaining, ResponseWriter interception, and Context caveats.
Examples
Uses a REST ServeMux, request logs, duration and status metrics, curl requests, and trace-ID propagation.
What it assumes
Assumes familiarity with higher-order functions and uses interfaces and closures to construct middleware.
What you can do after
Build it from scratch: chain HTTP wrappers that log requests, collect response metrics, and propagate trace IDs.
How it connects
Connects composition, higher-order functions, interfaces, http.Handler, Context, slog.Logger, ResponseWriter, and field embedding.

Also explained in

Compare how 10 books explain middleware →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.