feat(api): normalise OpenAPI server metadata
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
5b59a1dd10
commit
c48effb6b7
7 changed files with 48 additions and 16 deletions
|
|
@ -230,6 +230,7 @@ func (c *OpenAPIClient) loadSpec() error {
|
|||
}
|
||||
}
|
||||
}
|
||||
c.servers = normaliseServers(c.servers)
|
||||
|
||||
if c.baseURL == "" {
|
||||
for _, server := range c.servers {
|
||||
|
|
|
|||
|
|
@ -278,8 +278,9 @@ info:
|
|||
title: Test API
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: " `+srv.URL+` "
|
||||
- url: /
|
||||
- url: `+srv.URL+`
|
||||
- url: " `+srv.URL+` "
|
||||
paths:
|
||||
/hello:
|
||||
get:
|
||||
|
|
|
|||
15
openapi.go
15
openapi.go
|
|
@ -37,17 +37,12 @@ func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) {
|
|||
},
|
||||
}
|
||||
|
||||
if len(sb.Servers) > 0 {
|
||||
servers := make([]map[string]any, 0, len(sb.Servers))
|
||||
for _, server := range sb.Servers {
|
||||
if server == "" {
|
||||
continue
|
||||
}
|
||||
servers = append(servers, map[string]any{"url": server})
|
||||
}
|
||||
if len(servers) > 0 {
|
||||
spec["servers"] = servers
|
||||
if servers := normaliseServers(sb.Servers); len(servers) > 0 {
|
||||
out := make([]map[string]any, 0, len(servers))
|
||||
for _, server := range servers {
|
||||
out = append(out, map[string]any{"url": server})
|
||||
}
|
||||
spec["servers"] = out
|
||||
}
|
||||
|
||||
// Add component schemas for the response envelope.
|
||||
|
|
|
|||
|
|
@ -779,9 +779,10 @@ func TestSpecBuilder_Good_Servers(t *testing.T) {
|
|||
Title: "Test",
|
||||
Version: "1.0.0",
|
||||
Servers: []string{
|
||||
"https://api.example.com",
|
||||
" https://api.example.com ",
|
||||
"/",
|
||||
"",
|
||||
"https://api.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -800,7 +801,7 @@ func TestSpecBuilder_Good_Servers(t *testing.T) {
|
|||
t.Fatalf("expected servers array, got %T", spec["servers"])
|
||||
}
|
||||
if len(servers) != 2 {
|
||||
t.Fatalf("expected 2 non-empty servers, got %d", len(servers))
|
||||
t.Fatalf("expected 2 normalised servers, got %d", len(servers))
|
||||
}
|
||||
|
||||
first := servers[0].(map[string]any)
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func WithSwagger(title, description, version string) Option {
|
|||
// server list through both the runtime Swagger UI and exported OpenAPI files.
|
||||
func WithSwaggerServers(servers ...string) Option {
|
||||
return func(e *Engine) {
|
||||
e.swaggerServers = append([]string(nil), servers...)
|
||||
e.swaggerServers = normaliseServers(servers)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
34
servers.go
Normal file
34
servers.go
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package api
|
||||
|
||||
import "strings"
|
||||
|
||||
// normaliseServers trims whitespace, removes empty entries, and preserves
|
||||
// the first occurrence of each server URL.
|
||||
func normaliseServers(servers []string) []string {
|
||||
if len(servers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
cleaned := make([]string, 0, len(servers))
|
||||
seen := make(map[string]struct{}, len(servers))
|
||||
|
||||
for _, server := range servers {
|
||||
server = strings.TrimSpace(server)
|
||||
if server == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[server]; ok {
|
||||
continue
|
||||
}
|
||||
seen[server] = struct{}{}
|
||||
cleaned = append(cleaned, server)
|
||||
}
|
||||
|
||||
if len(cleaned) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cleaned
|
||||
}
|
||||
|
|
@ -263,7 +263,7 @@ func TestSwagger_Good_UsesServerMetadata(t *testing.T) {
|
|||
|
||||
e, err := api.New(
|
||||
api.WithSwagger("Server API", "Server metadata test", "1.0.0"),
|
||||
api.WithSwaggerServers("https://api.example.com", "/", ""),
|
||||
api.WithSwaggerServers(" https://api.example.com ", "/", "", "https://api.example.com"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
|
@ -293,7 +293,7 @@ func TestSwagger_Good_UsesServerMetadata(t *testing.T) {
|
|||
t.Fatalf("expected servers array, got %T", doc["servers"])
|
||||
}
|
||||
if len(servers) != 2 {
|
||||
t.Fatalf("expected 2 servers, got %d", len(servers))
|
||||
t.Fatalf("expected 2 normalised servers, got %d", len(servers))
|
||||
}
|
||||
|
||||
first := servers[0].(map[string]any)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue