Let a handler's flush reach the client through the access log (closes #191)
check / check (push) Successful in 3m15s

The access log's response writer had no Unwrap method, so
http.ResponseController stopped at it and a handler's Flush returned
http.ErrNotSupported. It now has one.

With metrics on, adding Unwrap alone is not enough: go-http-metrics'
writer only passes a flush on when the writer inside it has a Flush
method, and it sat inside Logging, so the flush silently did nothing.
Metrics is now registered outside Logging, and the README's middleware
list follows.

A new test flushes through the production router, with the defaults
and with metrics and Sentry on, on a global route and inside an admin
page route group.

Model: opus-5-5
This commit is contained in:
2026-10-02 08:46:08 +00:00
parent 5b1d283d06
commit e88192aa9a
5 changed files with 119 additions and 9 deletions
+7 -3
View File
@@ -2979,10 +2979,10 @@ Applied to all routes in this order:
2. **SecurityHeaders** — Production security headers on every response
(HSTS, X-Content-Type-Options, X-Frame-Options, CSP, Referrer-Policy,
Permissions-Policy)
3. **Logging** — Structured request logging (method, URL, status,
latency, remote IP, user agent, request ID)
4. **Metrics** — Prometheus HTTP metrics (if `METRICS_USERNAME` and
3. **Metrics** — Prometheus HTTP metrics (if `METRICS_USERNAME` and
`METRICS_PASSWORD` are both set)
4. **Logging** — Structured request logging (method, URL, status,
latency, remote IP, user agent, request ID)
5. **CORS** — Cross-origin resource sharing headers
6. **Timeout** — 60-second request timeout
7. **Recoverer** — Panic recovery: one `ERROR` record through
@@ -3002,6 +3002,10 @@ local record instead of nothing. What that placement gives up is
recovery of a panic in the six entries above it, none of which does
more than set a header or start a timer.
Metrics sits outside Logging so that a handler's flush reaches the
client: go-http-metrics' writer passes a flush on only when the writer
inside it has a `Flush` method, and the access log's writer has none.
Each admin page route group (`/pages`, `/user/*`, `/hooks`,
`/hook/*`) starts with its own **Recoverer** and, if `SENTRY_DSN` is
set, its own **Sentry** error reporting. That Recoverer answers a panic