diff --git a/paths/paths.go b/paths/paths.go index 4510b2e..2976195 100644 --- a/paths/paths.go +++ b/paths/paths.go @@ -200,7 +200,21 @@ func getBasePaths(document *v3.Document) []string { // extract base path from document to check against paths. var basePaths []string for _, s := range document.Servers { - u, _ := url.Parse(s.URL) + var u *url.URL = nil + u, err := url.Parse(s.URL) + + // if the host contains special characters, we should attempt to split and parse only the relative path + if err != nil { + // split at first occurrence + _, serverPath, _ := strings.Cut(strings.Replace(s.URL, "//", "", 1), "/") + + if !strings.HasPrefix(serverPath, "/") { + serverPath = "/" + serverPath + } + + u, _ = url.Parse(serverPath) + } + if u != nil && u.Path != "" { basePaths = append(basePaths, u.Path) } diff --git a/paths/paths_test.go b/paths/paths_test.go index 5eff42f..aff1451 100644 --- a/paths/paths_test.go +++ b/paths/paths_test.go @@ -659,3 +659,41 @@ paths: assert.Equal(t, "GET Path '/not_here' not found", errs[0].Message) } + +func TestGetBasePaths(t *testing.T) { + spec := `openapi: 3.1.0 +servers: + - url: 'https://things.com/' + - url: 'https://things.com/some/path' + - url: 'https://things.com/more//paths//please' + - url: 'https://{invalid}.com/' + - url: 'https://{invalid}.com/some/path' + - url: 'https://{invalid}.com/more//paths//please' + - url: 'https://{invalid}.com//even//more//paths//please' +paths: + /dishy: + get: + operationId: one +` + + doc, err := libopenapi.NewDocument([]byte(spec)) + if err != nil { + t.Fatal(err) + } + m, _ := doc.BuildV3Model() + + basePaths := getBasePaths(&m.Model) + + expectedPaths := []string{ + "/", + "/some/path", + "/more//paths//please", + "/", + "/some/path", + "/more//paths//please", + "/even//more//paths//please", + } + + assert.Equal(t, expectedPaths, basePaths) + +}