httpsnoop

Captures HTTP status code, duration, and bytes written from Go handlers without breaking ResponseWriter's optional interfaces.

Library
Go
vv1.1.0
1,166stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
46/100Fair
Development Activity24
Maintenance28
Community44
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
70/100Good
Architecture85
Code Quality85
Innovation75
Learning Curve35

httpsnoop is a small Go library for capturing HTTP handler metrics — status code, response duration, and bytes written — without the interface-breaking side effects that come from naively wrapping http.ResponseWriter. Many response writers implement extra interfaces such as http.Flusher, http.Hijacker, http.CloseNotifier, http.Pusher, or io.ReaderFrom, and a wrapper that fails to preserve them can silently break streaming, websocket upgrades, or connection hijacking in production.

The package solves this with CaptureMetrics and Wrap, a generated, allocation-light dispatcher that detects exactly which optional interfaces the underlying ResponseWriter implements and returns a wrapped writer exposing that exact same combination, routing calls through user-supplied hook functions. The result is a drop-in instrumentation layer that’s safe to use inside reverse proxies, middleware chains, and observability tooling.

What You Get

  • CaptureMetrics / CaptureMetricsFn helpers that wrap a handler or a ResponseWriter directly and return Code, Duration, and Written for a single request/response cycle
  • Wrap(w, Hooks) — a generic, hook-based ResponseWriter wrapper for building custom instrumentation or middleware
  • Full interface-preserving support for http.Flusher, http.Hijacker, http.CloseNotifier, http.Pusher, io.ReaderFrom, io.StringWriter, and the Go 1.20+/1.21+ deadline, FlushError, and EnableFullDuplex interfaces
  • Unwrap helper to recover the original ResponseWriter through any number of stacked httpsnoop wrapper layers

Common Use Cases

  • Logging middleware that needs an accurate status code and response size per request
  • Prometheus or OpenTelemetry HTTP instrumentation built on top of Hooks
  • Reverse proxies and API gateways that must preserve streaming and hijacking behavior
  • Building custom request/response observability tooling on top of the standard library’s http.Handler

Under The Hood

Architecture The package is organized around three parts: capture_metrics.go (the public API — CaptureMetrics, CaptureMetricsFn, and Metrics.CaptureMetrics), wrap_generated.go (a large generated file implementing hundreds of combinatorial ResponseWriter wrapper variant types over a shared rwState struct via zero-cost pointer conversion), and codegen/main.go (the generator that defines the interface list — http.ResponseWriter, http.Flusher, httpFlushError, http.CloseNotifier, http.Hijacker, io.ReaderFrom, deadliner, fullDuplexEnabler, http.Pusher, io.StringWriter — and emits per-combination types, do<Method> dispatch funcs, and the hook-wiring logic inside Wrap). Rather than reflection or a runtime type-switch on every call, Wrap computes a combo bitmask once by type-asserting the input ResponseWriter, then returns a pointer cast to one of the pre-generated combination types whose method set exactly matches what the original writer supports — so every subsequent method call dispatches directly through rwState.do<Method> with no reflection in the hot path. Changing the core abstraction (the Hooks struct or the interface list in codegen/main.go) requires regenerating both wrap_generated.go and its matching test file via go generate.

Tech Stack Go 1.25, standard library only — go.mod declares zero third-party dependencies. The package uses net/http, io, net, bufio, and time in the generated wrapper, and bytes/errors/testing in tests. Build and verification run through a Makefile (go test, go vet, gofmt checks) and a GitHub Actions workflow (.github/workflows/main.yaml); code generation is driven by //go:generate go run codegen/main.go in docs.go, keeping generation and consumption in the same module rather than a separate build step.

Code Quality Tests exist and are extensive: capture_metrics_test.go, wrap_test.go, unwrap_test.go, plus a generated wrap_generated_test.go that exhaustively exercises every supported interface combination against a synthetic ResponseWriter, verifying both the interface set exposed by Wrap and correct Unwrap behavior. Benchmarks (wrap_bench_test.go, capture_metrics_bench_test.go) track the overhead CaptureMetrics adds over a bare handler. Error handling favors explicit returns; the one panic("unreachable") in the generated Wrap switch is a defensive guard against a combination that should be impossible to reach given the preceding type assertions. Naming and structure are idiomatic stdlib-style Go, with CI wired via GitHub Actions and no assertion library or mocking framework beyond testing and hand-written fakes.

What Makes It Unique The distinguishing choice is generating a combinatorial set of concrete wrapper types at build time instead of using a single fat wrapper struct with reflection-based interface checks per call, or the naive single-struct approach the README explicitly warns readers away from. This trades extra generated code for compile-time-exhaustive interface preservation and reflection-free dispatch, directly targeting a documented, easy-to-get-wrong problem: a ResponseWriter wrapper silently dropping Flusher, Hijacker, or CloseNotifier support and breaking streaming or hijacking in production. The package also carries targeted compatibility fallbacks — routing WriteString through a configured Write hook, and FlushError through a configured Flush hook — so newer optional interfaces don’t change behavior for callers who only configured the older hooks.

Used by 5 apps in this directory

Go
54%
Apache 2.0

Authgear

Authentication

2,028

Open-source, self-hostable authentication platform with passkeys, biometric login, SSO, MFA, and GraphQL admin API — a full Auth0/Clerk/Firebase alternative for SaaS and mobile apps.

View details
88
Repo Health
81
Technical
68
Dependency
Built with
Go54%
HTML25%
TypeScript18%
Updated 3 days ago
Go
72%
Other

Convoy

Developer Tools · Devops

2,862

Convoy is an open-source, cloud-native webhooks gateway that ingests events over HTTP or straight from Kafka, SQS, Google Pub/Sub, and RabbitMQ, then reliably delivers them to subscriber endpoints with signed payloads, automatic retries, circuit breaking, and JavaScript-based transformations.

View details
88
Repo Health
81
Technical
65
Dependency
Built with
Go72%
TypeScript15%
HTML12%
Updated 5 days ago
Go
95%
Apache 2.0

Nakama

Developer Tools · Game Development

13,286

Open-source game backend server with built-in multiplayer, matchmaking, leaderboards, chat, authentication, and storage — deploy anywhere via Docker or binary.

View details
90
Repo Health
73
Technical
74
Dependency
Built with
Go95%
Updated 2 days ago
Go
90%
AGPL 3.0

Pyroscope

Monitoring · Devops · Developer Tools

11,649

An open-source, horizontally scalable continuous profiling platform that pinpoints CPU, memory, and I/O bottlenecks down to the exact line of code, built by Grafana Labs alongside Loki, Tempo, and Mimir.

View details
91
Repo Health
89
Technical
65
Dependency
Built with
Go90%
Updated 2 days ago
Go
97%
BSD 3

Weaviate

Databases · Search

16,785

Open-source vector database combining semantic search, hybrid queries, RAG, and image search in a single cloud-native system built for production scale.

View details
90
Repo Health
85
Technical
68
Dependency
Built with
Go97%
Updated 2 days ago

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search