Show the API reference with Redoc
Replace the hand-built reference page with Redoc rendering the generated OpenAPI document. The bundle is fetched by package.nix (pinned hash) and served from the UI's own address; only that page gets a style nonce and worker-src blob: in its CSP. The spec now explains authentication, saved-not-applied, ETags (If-Match, 409) and errors, documents the ETag header, gives each operation a curl sample, and no longer names MCP tools. Area GETs no longer emit "parameters": null, which Redoc could not render. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AeFqV9dZrK6nipHkPfyM4F
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -264,14 +265,28 @@ func TestLiveSettingsValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAreasOnReferencePage(t *testing.T) {
|
||||
a, h, _ := areaApp(t)
|
||||
cookie := login(t, h)
|
||||
_ = a
|
||||
body := do(h, "GET", "/apireference", nil, cookie).Body.String()
|
||||
for _, want := range []string{"/api/v1/settings/router/lans", "/api/v1/settings/router/firewall", "<name>.vlan", "null or integer between 1 and 4094", "Settings areas"} {
|
||||
if !strings.Contains(body, want) {
|
||||
t.Errorf("%q is missing from the reference page", want)
|
||||
// Viewers (Redoc) fail on a null where the OpenAPI document needs a list.
|
||||
func TestSpecHasNoNulls(t *testing.T) {
|
||||
a, _, _ := areaApp(t)
|
||||
spec := openAPISpec("1.2.3", a.settingsSchema(), "router.example")
|
||||
var walk func(path string, v any)
|
||||
walk = func(path string, v any) {
|
||||
switch x := v.(type) {
|
||||
case nil:
|
||||
t.Errorf("null at %s", path)
|
||||
case map[string]any:
|
||||
for k, c := range x {
|
||||
walk(path+"/"+k, c)
|
||||
}
|
||||
case []any:
|
||||
for i, c := range x {
|
||||
walk(fmt.Sprintf("%s/%d", path, i), c)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Round trip, as the served document is.
|
||||
data, _ := json.Marshal(spec)
|
||||
var doc any
|
||||
_ = json.Unmarshal(data, &doc)
|
||||
walk("", doc)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user