@@ -0,0 +1,57 @@ |
| 1 | +// SPDX-License-Identifier: AGPL-3.0-or-later |
| 2 | + |
| 3 | +package handlers |
| 4 | + |
| 5 | +import ( |
| 6 | + "io" |
| 7 | + "log/slog" |
| 8 | + "net/http" |
| 9 | + "net/http/httptest" |
| 10 | + "strings" |
| 11 | + "testing" |
| 12 | + |
| 13 | + "github.com/go-chi/chi/v5" |
| 14 | +) |
| 15 | + |
| 16 | +// /metrics MUST be served uncompressed even when the scraper advertises |
| 17 | +// gzip support. Alloy 1.16 (and several other prom-compatible scrapers) |
| 18 | +// mis-handle Content-Encoding: gzip and parse the raw 0x1f magic byte |
| 19 | +// as text, failing the scrape silently with up=0. |
| 20 | +func TestMetricsServedUncompressedWithGzipAccept(t *testing.T) { |
| 21 | + t.Parallel() |
| 22 | + |
| 23 | + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 24 | + w.Header().Set("Content-Type", "text/plain; version=0.0.4; charset=utf-8") |
| 25 | + _, _ = io.WriteString(w, "# HELP test_metric A test metric\n# TYPE test_metric counter\ntest_metric 1\n") |
| 26 | + }) |
| 27 | + |
| 28 | + r := chi.NewRouter() |
| 29 | + if _, _, _, err := RegisterChi(r, Deps{ |
| 30 | + Logger: slog.New(slog.NewTextHandler(io.Discard, nil)), |
| 31 | + TemplatesFS: testTemplatesFS(t), |
| 32 | + StaticFS: testStaticFS(t), |
| 33 | + LogoSVG: `<svg xmlns="http://www.w3.org/2000/svg"><title>shithub</title></svg>`, |
| 34 | + MetricsHandler: handler, |
| 35 | + }); err != nil { |
| 36 | + t.Fatalf("RegisterChi: %v", err) |
| 37 | + } |
| 38 | + |
| 39 | + req := httptest.NewRequest(http.MethodGet, "/metrics", nil) |
| 40 | + req.Header.Set("Accept-Encoding", "gzip") |
| 41 | + rec := httptest.NewRecorder() |
| 42 | + r.ServeHTTP(rec, req) |
| 43 | + |
| 44 | + if got := rec.Code; got != http.StatusOK { |
| 45 | + t.Fatalf("status = %d, want 200", got) |
| 46 | + } |
| 47 | + if enc := rec.Header().Get("Content-Encoding"); enc != "" { |
| 48 | + t.Errorf("Content-Encoding = %q, want empty (Prometheus scrapers expect plain text)", enc) |
| 49 | + } |
| 50 | + body := rec.Body.String() |
| 51 | + if !strings.Contains(body, "test_metric 1") { |
| 52 | + t.Errorf("body missing metric text; got %q", body) |
| 53 | + } |
| 54 | + if strings.HasPrefix(body, "\x1f\x8b") { |
| 55 | + t.Errorf("body starts with gzip magic bytes — middleware compressed /metrics") |
| 56 | + } |
| 57 | +} |