diff --git a/pkg/server/api/complianceportal/v1/seo.go b/pkg/server/api/complianceportal/v1/seo.go index eabc41d6f..cd709b2c5 100644 --- a/pkg/server/api/complianceportal/v1/seo.go +++ b/pkg/server/api/complianceportal/v1/seo.go @@ -76,10 +76,11 @@ func SEOFromRequest(r *http.Request, pageBaseURL string) (htmlLang, canonical st // portalOrigin returns scheme://host from pageBaseURL, dropping any path, // query, or fragment. Callers may pass a full request URL by mistake. +// Relative or malformed values yield "" so SEO links are omitted. func portalOrigin(pageBaseURL string) string { parsed, err := url.Parse(pageBaseURL) if err != nil || parsed.Scheme == "" || parsed.Host == "" { - return strings.TrimRight(pageBaseURL, "/") + return "" } return (&url.URL{Scheme: parsed.Scheme, Host: parsed.Host}).String() diff --git a/pkg/server/api/complianceportal/v1/seo_test.go b/pkg/server/api/complianceportal/v1/seo_test.go index 06b203fa1..1d9d6163b 100644 --- a/pkg/server/api/complianceportal/v1/seo_test.go +++ b/pkg/server/api/complianceportal/v1/seo_test.go @@ -124,3 +124,22 @@ func TestSEOFromRequest_EmptyBaseURLOmitsLinks(t *testing.T) { assert.Empty(t, canonical) assert.Nil(t, hreflang) } + +func TestSEOFromRequest_RelativeBaseURLOmitsLinks(t *testing.T) { + t.Parallel() + + req, err := http.NewRequest( + http.MethodGet, + "https://trust.acme.com/fr/documents", + nil, + ) + require.NoError(t, err) + + lang, canonical, hreflang := complianceportal_v1.SEOFromRequest( + req, + "/fr/documents", + ) + assert.Equal(t, "fr", lang) + assert.Empty(t, canonical) + assert.Nil(t, hreflang) +}