From aff54403c692ffb66a08e4456d619bae5c5a9394 Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 1 Apr 2026 17:57:16 +0000 Subject: [PATCH] fix(api): compose swagger server metadata Co-Authored-By: Virgil --- options.go | 6 +++--- swagger_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/options.go b/options.go index 6378e0a..c0d986c 100644 --- a/options.go +++ b/options.go @@ -130,11 +130,11 @@ func WithSwagger(title, description, version string) Option { } // WithSwaggerServers adds OpenAPI server metadata to the generated Swagger spec. -// Empty strings are ignored. Combine it with WithSwagger() to expose the same -// server list through both the runtime Swagger UI and exported OpenAPI files. +// Empty strings are ignored. Multiple calls append and normalise the combined +// server list so callers can compose metadata across options. func WithSwaggerServers(servers ...string) Option { return func(e *Engine) { - e.swaggerServers = normaliseServers(servers) + e.swaggerServers = normaliseServers(append(e.swaggerServers, servers...)) } } diff --git a/swagger_test.go b/swagger_test.go index 689361e..70bfe66 100644 --- a/swagger_test.go +++ b/swagger_test.go @@ -307,6 +307,54 @@ func TestSwagger_Good_UsesServerMetadata(t *testing.T) { } } +func TestSwagger_Good_AppendsServerMetadataAcrossCalls(t *testing.T) { + gin.SetMode(gin.TestMode) + + e, err := api.New( + api.WithSwagger("Server API", "Server metadata test", "1.0.0"), + api.WithSwaggerServers("https://api.example.com", "/"), + api.WithSwaggerServers(" https://docs.example.com ", "/", "https://api.example.com"), + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + srv := httptest.NewServer(e.Handler()) + defer srv.Close() + + resp, err := http.Get(srv.URL + "/swagger/doc.json") + if err != nil { + t.Fatalf("request failed: %v", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + t.Fatalf("failed to read body: %v", err) + } + + var doc map[string]any + if err := json.Unmarshal(body, &doc); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + + servers, ok := doc["servers"].([]any) + if !ok { + t.Fatalf("expected servers array, got %T", doc["servers"]) + } + if len(servers) != 3 { + t.Fatalf("expected 3 normalised servers, got %d", len(servers)) + } + + expected := []string{"https://api.example.com", "/", "https://docs.example.com"} + for i, want := range expected { + got := servers[i].(map[string]any)["url"] + if got != want { + t.Fatalf("expected server[%d] url=%q, got %v", i, want, got) + } + } +} + func TestSwagger_Good_ValidOpenAPI(t *testing.T) { gin.SetMode(gin.TestMode)