Skip to content

Commit

Permalink
Introduce (openapi3.*Server).BasePath() and `(openapi3.Servers).Bas…
Browse files Browse the repository at this point in the history
…ePath()` (#633)
  • Loading branch information
fenollp authored Oct 13, 2022
1 parent 138bfa0 commit e887ba8
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
32 changes: 32 additions & 0 deletions openapi3/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ func (servers Servers) Validate(ctx context.Context) error {
return nil
}

// BasePath returns the base path of the first server in the list, or /.
func (servers Servers) BasePath() (string, error) {
for _, server := range servers {
return server.BasePath()
}
return "/", nil
}

func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string) {
rawURL := parsedURL.String()
if i := strings.IndexByte(rawURL, '?'); i >= 0 {
Expand All @@ -49,6 +57,30 @@ type Server struct {
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
}

// BasePath returns the base path extracted from the default values of variables, if any.
// Assumes a valid struct (per Validate()).
func (server *Server) BasePath() (string, error) {
if server == nil {
return "/", nil
}

uri := server.URL
for name, svar := range server.Variables {
uri = strings.ReplaceAll(uri, "{"+name+"}", svar.Default)
}

u, err := url.ParseRequestURI(uri)
if err != nil {
return "", err
}

if bp := u.Path; bp != "" {
return bp, nil
}

return "/", nil
}

// MarshalJSON returns the JSON encoding of Server.
func (server *Server) MarshalJSON() ([]byte, error) {
return jsoninfo.MarshalStrictStruct(server)
Expand Down
85 changes: 85 additions & 0 deletions openapi3/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,88 @@ func newServerMatch(remaining string, args ...string) *serverMatch {
Args: args,
}
}

func TestServersBasePath(t *testing.T) {
for _, testcase := range []struct {
title string
servers Servers
expected string
}{
{
title: "empty servers",
servers: nil,
expected: "/",
},
{
title: "URL set, missing trailing slash",
servers: Servers{&Server{URL: "https://example.com"}},
expected: "/",
},
{
title: "URL set, with trailing slash",
servers: Servers{&Server{URL: "https://example.com/"}},
expected: "/",
},
{
title: "URL set",
servers: Servers{&Server{URL: "https://example.com/b/l/a"}},
expected: "/b/l/a",
},
{
title: "URL set with variables",
servers: Servers{&Server{
URL: "{scheme}://example.com/b/l/a",
Variables: map[string]*ServerVariable{
"scheme": {
Enum: []string{"http", "https"},
Default: "https",
},
},
}},
expected: "/b/l/a",
},
{
title: "URL set with variables in path",
servers: Servers{&Server{
URL: "http://example.com/b/{var1}/a",
Variables: map[string]*ServerVariable{
"var1": {
Default: "lllll",
},
},
}},
expected: "/b/lllll/a",
},
{
title: "URLs set with variables in path",
servers: Servers{
&Server{
URL: "http://example.com/b/{var2}/a",
Variables: map[string]*ServerVariable{
"var2": {
Default: "LLLLL",
},
},
},
&Server{
URL: "https://example.com/b/{var1}/a",
Variables: map[string]*ServerVariable{
"var1": {
Default: "lllll",
},
},
},
},
expected: "/b/LLLLL/a",
},
} {
t.Run(testcase.title, func(t *testing.T) {
err := testcase.servers.Validate(context.Background())
require.NoError(t, err)

got, err := testcase.servers.BasePath()
require.NoError(t, err)
require.Exactly(t, testcase.expected, got)
})
}
}

0 comments on commit e887ba8

Please sign in to comment.