Test that made-up methods share one metrics method label

The test sends two requests with made-up methods through the metrics
middleware and expects /metrics to count both under the method label
"other", and the handler to see each method as sent. It fails until the
middleware stops using every method name as its own label value.

Model: opus-5-5
This commit is contained in:
2026-10-15 19:01:28 +00:00
parent 742db9ceb1
commit afb94a14f0
@@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"slices"
"strings"
"testing"
@@ -314,6 +315,58 @@ func requestCountsByHandler(
return counts
}
// TestMetricsGivesMadeUpMethodsOneLabel checks that the metrics middleware
// gives requests with methods that are not standard ones a single method
// label, "other", and still serves each request with the method it was sent
// with. With a label per method, any client could add series to the
// registry without limit by making up a new method for each request.
func TestMetricsGivesMadeUpMethodsOneLabel(t *testing.T) {
t.Parallel()
// The line /metrics shows once both made-up methods have been served.
const want = `http_request_duration_seconds_count{` +
`code="200",handler="unmatched",method="other",service=""} 2`
registry := prometheus.NewRegistry()
mw := &Middleware{
log: slog.Default(),
config: &config.Config{},
metricsRegistry: registry,
}
var served []string
handler := mw.Metrics()(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
served = append(served, r.Method)
w.WriteHeader(http.StatusOK)
}))
methods := []string{"FROBNICATE", "WIBBLE"}
for _, method := range methods {
handler.ServeHTTP(httptest.NewRecorder(), httptest.NewRequestWithContext(
t.Context(), method, "/", nil))
}
t.Logf("methods the handler was served: %v", served)
if !slices.Equal(served, methods) {
t.Errorf("methods the handler was served = %v, want %v",
served, methods)
}
rec := httptest.NewRecorder()
promhttp.HandlerFor(registry, promhttp.HandlerOpts{}).ServeHTTP(rec,
httptest.NewRequestWithContext(
t.Context(), http.MethodGet, "/metrics", nil))
if !strings.Contains(rec.Body.String(), want) {
t.Errorf("/metrics does not count both made-up methods as one; "+
"want the line %q in:\n%s", want, rec.Body.String())
}
}
// TestLoggingLeavesOutSubmittedSigningKey checks that a login, a POST /
// whose form carries the signing key, leaves no trace of the key in the
// request's log line.