From 5971951c877a39950c7d35afba8a551487ca7b58 Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 14:25:59 +0000 Subject: [PATCH] fix(cmd/api): trim spec metadata inputs --- cmd/api/cmd_test.go | 61 +++++++++++++++++++++++++++++++++++++++++ cmd/api/spec_builder.go | 24 ++++++++-------- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/cmd/api/cmd_test.go b/cmd/api/cmd_test.go index 72521be..12fbd83 100644 --- a/cmd/api/cmd_test.go +++ b/cmd/api/cmd_test.go @@ -234,6 +234,67 @@ func TestAPISpecCmd_Good_SummaryPopulatesSpecInfo(t *testing.T) { } } +func TestNewSpecBuilder_Good_TrimsMetadata(t *testing.T) { + builder, err := newSpecBuilder(specBuilderConfig{ + title: " API Title ", + summary: " API Summary ", + description: " API Description ", + version: " 1.2.3 ", + termsURL: " https://example.com/terms ", + contactName: " API Support ", + contactURL: " https://example.com/support ", + contactEmail: " support@example.com ", + licenseName: " EUPL-1.2 ", + licenseURL: " https://eupl.eu/1.2/en/ ", + externalDocsDescription: " Developer guide ", + externalDocsURL: " https://example.com/docs ", + servers: " https://api.example.com , / ", + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if builder.Title != "API Title" { + t.Fatalf("expected trimmed title, got %q", builder.Title) + } + if builder.Summary != "API Summary" { + t.Fatalf("expected trimmed summary, got %q", builder.Summary) + } + if builder.Description != "API Description" { + t.Fatalf("expected trimmed description, got %q", builder.Description) + } + if builder.Version != "1.2.3" { + t.Fatalf("expected trimmed version, got %q", builder.Version) + } + if builder.TermsOfService != "https://example.com/terms" { + t.Fatalf("expected trimmed terms URL, got %q", builder.TermsOfService) + } + if builder.ContactName != "API Support" { + t.Fatalf("expected trimmed contact name, got %q", builder.ContactName) + } + if builder.ContactURL != "https://example.com/support" { + t.Fatalf("expected trimmed contact URL, got %q", builder.ContactURL) + } + if builder.ContactEmail != "support@example.com" { + t.Fatalf("expected trimmed contact email, got %q", builder.ContactEmail) + } + if builder.LicenseName != "EUPL-1.2" { + t.Fatalf("expected trimmed licence name, got %q", builder.LicenseName) + } + if builder.LicenseURL != "https://eupl.eu/1.2/en/" { + t.Fatalf("expected trimmed licence URL, got %q", builder.LicenseURL) + } + if builder.ExternalDocsDescription != "Developer guide" { + t.Fatalf("expected trimmed external docs description, got %q", builder.ExternalDocsDescription) + } + if builder.ExternalDocsURL != "https://example.com/docs" { + t.Fatalf("expected trimmed external docs URL, got %q", builder.ExternalDocsURL) + } + if len(builder.Servers) != 2 || builder.Servers[0] != "https://api.example.com" || builder.Servers[1] != "/" { + t.Fatalf("expected trimmed servers, got %v", builder.Servers) + } +} + func TestAPISpecCmd_Good_CacheAndI18nFlagsPopulateSpec(t *testing.T) { root := &cli.Command{Use: "root"} AddAPICommands(root) diff --git a/cmd/api/spec_builder.go b/cmd/api/spec_builder.go index edc04e1..f271504 100644 --- a/cmd/api/spec_builder.go +++ b/cmd/api/spec_builder.go @@ -52,10 +52,10 @@ func newSpecBuilder(cfg specBuilderConfig) (*goapi.SpecBuilder, error) { cacheTTLValid := parsePositiveDuration(cacheTTL) builder := &goapi.SpecBuilder{ - Title: cfg.title, - Summary: cfg.summary, - Description: cfg.description, - Version: cfg.version, + Title: strings.TrimSpace(cfg.title), + Summary: strings.TrimSpace(cfg.summary), + Description: strings.TrimSpace(cfg.description), + Version: strings.TrimSpace(cfg.version), SwaggerEnabled: swaggerPath != "", SwaggerPath: swaggerPath, GraphQLEnabled: graphqlPath != "" || cfg.graphqlPlayground, @@ -72,15 +72,15 @@ func newSpecBuilder(cfg specBuilderConfig) (*goapi.SpecBuilder, error) { CacheMaxEntries: cfg.cacheMaxEntries, CacheMaxBytes: cfg.cacheMaxBytes, I18nDefaultLocale: strings.TrimSpace(cfg.i18nDefaultLocale), - TermsOfService: cfg.termsURL, - ContactName: cfg.contactName, - ContactURL: cfg.contactURL, - ContactEmail: cfg.contactEmail, + TermsOfService: strings.TrimSpace(cfg.termsURL), + ContactName: strings.TrimSpace(cfg.contactName), + ContactURL: strings.TrimSpace(cfg.contactURL), + ContactEmail: strings.TrimSpace(cfg.contactEmail), Servers: parseServers(cfg.servers), - LicenseName: cfg.licenseName, - LicenseURL: cfg.licenseURL, - ExternalDocsDescription: cfg.externalDocsDescription, - ExternalDocsURL: cfg.externalDocsURL, + LicenseName: strings.TrimSpace(cfg.licenseName), + LicenseURL: strings.TrimSpace(cfg.licenseURL), + ExternalDocsDescription: strings.TrimSpace(cfg.externalDocsDescription), + ExternalDocsURL: strings.TrimSpace(cfg.externalDocsURL), AuthentikIssuer: strings.TrimSpace(cfg.authentikIssuer), AuthentikClientID: strings.TrimSpace(cfg.authentikClientID), AuthentikTrustedProxy: cfg.authentikTrustedProxy,