From 4d9004ab31a6064af741fbb73758bd8844964c6f Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 14 Apr 2026 10:01:43 +0300 Subject: z2: HTTP report query aliases and Gemtext Content-Type Accept Category, Metric, and OutputFormat as alternate query keys alongside category, metric, output-format. Serve Gemtext reports with text/gemini; assert Content-Type in daemon tests. Builds on y2 daemon GET /report reusing ParseReportQuery and WriteReports. Made-with: Cursor --- internal/daemon/daemon.go | 2 ++ internal/daemon/daemon_test.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'internal/daemon') diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 4e2402f..a4b1a3e 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -101,6 +101,8 @@ func reportContentType(f goprecords.OutputFormat) string { switch f { case goprecords.FormatMarkdown: return "text/markdown; charset=utf-8" + case goprecords.FormatGemtext: + return "text/gemini; charset=utf-8" default: return "text/plain; charset=utf-8" } diff --git a/internal/daemon/daemon_test.go b/internal/daemon/daemon_test.go index 38878fa..b140c9e 100644 --- a/internal/daemon/daemon_test.go +++ b/internal/daemon/daemon_test.go @@ -54,6 +54,9 @@ func TestReport(t *testing.T) { if res.StatusCode != http.StatusOK { t.Fatalf("status %d", res.StatusCode) } + if ct := res.Header.Get("Content-Type"); ct != "text/plain; charset=utf-8" { + t.Fatalf("Content-Type %q", ct) + } b, err := io.ReadAll(res.Body) if err != nil { t.Fatal(err) @@ -63,6 +66,45 @@ func TestReport(t *testing.T) { } } +func TestReportQueryAliases(t *testing.T) { + fixtures := filepath.Join("..", "..", "fixtures") + srv := httptest.NewServer(Handler(fixtures)) + defer srv.Close() + res, err := http.Get(srv.URL + "/report?Category=Host&Metric=Uptime&limit=2&OutputFormat=Markdown") + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + t.Fatalf("status %d", res.StatusCode) + } + if ct := res.Header.Get("Content-Type"); ct != "text/markdown; charset=utf-8" { + t.Fatalf("Content-Type %q", ct) + } + b, _ := io.ReadAll(res.Body) + body := string(b) + if !strings.Contains(body, "# Top") || !strings.Contains(body, "```") { + t.Fatalf("expected markdown heading and fence, got %q", b) + } +} + +func TestReportGemtextContentType(t *testing.T) { + fixtures := filepath.Join("..", "..", "fixtures") + srv := httptest.NewServer(Handler(fixtures)) + defer srv.Close() + res, err := http.Get(srv.URL + "/report?output-format=Gemtext&limit=2") + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + if res.StatusCode != http.StatusOK { + t.Fatalf("status %d", res.StatusCode) + } + if ct := res.Header.Get("Content-Type"); ct != "text/gemini; charset=utf-8" { + t.Fatalf("Content-Type %q", ct) + } +} + func TestReportBadQuery(t *testing.T) { srv := httptest.NewServer(Handler(t.TempDir())) defer srv.Close() -- cgit v1.2.3