Skip to content

Commit e887ba8

Browse files
authored
Introduce (openapi3.*Server).BasePath() and (openapi3.Servers).BasePath() (#633)
1 parent 138bfa0 commit e887ba8

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

openapi3/server.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ func (servers Servers) Validate(ctx context.Context) error {
2525
return nil
2626
}
2727

28+
// BasePath returns the base path of the first server in the list, or /.
29+
func (servers Servers) BasePath() (string, error) {
30+
for _, server := range servers {
31+
return server.BasePath()
32+
}
33+
return "/", nil
34+
}
35+
2836
func (servers Servers) MatchURL(parsedURL *url.URL) (*Server, []string, string) {
2937
rawURL := parsedURL.String()
3038
if i := strings.IndexByte(rawURL, '?'); i >= 0 {
@@ -49,6 +57,30 @@ type Server struct {
4957
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
5058
}
5159

60+
// BasePath returns the base path extracted from the default values of variables, if any.
61+
// Assumes a valid struct (per Validate()).
62+
func (server *Server) BasePath() (string, error) {
63+
if server == nil {
64+
return "/", nil
65+
}
66+
67+
uri := server.URL
68+
for name, svar := range server.Variables {
69+
uri = strings.ReplaceAll(uri, "{"+name+"}", svar.Default)
70+
}
71+
72+
u, err := url.ParseRequestURI(uri)
73+
if err != nil {
74+
return "", err
75+
}
76+
77+
if bp := u.Path; bp != "" {
78+
return bp, nil
79+
}
80+
81+
return "/", nil
82+
}
83+
5284
// MarshalJSON returns the JSON encoding of Server.
5385
func (server *Server) MarshalJSON() ([]byte, error) {
5486
return jsoninfo.MarshalStrictStruct(server)

openapi3/server_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,88 @@ func newServerMatch(remaining string, args ...string) *serverMatch {
116116
Args: args,
117117
}
118118
}
119+
120+
func TestServersBasePath(t *testing.T) {
121+
for _, testcase := range []struct {
122+
title string
123+
servers Servers
124+
expected string
125+
}{
126+
{
127+
title: "empty servers",
128+
servers: nil,
129+
expected: "/",
130+
},
131+
{
132+
title: "URL set, missing trailing slash",
133+
servers: Servers{&Server{URL: "https://example.com"}},
134+
expected: "/",
135+
},
136+
{
137+
title: "URL set, with trailing slash",
138+
servers: Servers{&Server{URL: "https://example.com/"}},
139+
expected: "/",
140+
},
141+
{
142+
title: "URL set",
143+
servers: Servers{&Server{URL: "https://example.com/b/l/a"}},
144+
expected: "/b/l/a",
145+
},
146+
{
147+
title: "URL set with variables",
148+
servers: Servers{&Server{
149+
URL: "{scheme}://example.com/b/l/a",
150+
Variables: map[string]*ServerVariable{
151+
"scheme": {
152+
Enum: []string{"http", "https"},
153+
Default: "https",
154+
},
155+
},
156+
}},
157+
expected: "/b/l/a",
158+
},
159+
{
160+
title: "URL set with variables in path",
161+
servers: Servers{&Server{
162+
URL: "http://example.com/b/{var1}/a",
163+
Variables: map[string]*ServerVariable{
164+
"var1": {
165+
Default: "lllll",
166+
},
167+
},
168+
}},
169+
expected: "/b/lllll/a",
170+
},
171+
{
172+
title: "URLs set with variables in path",
173+
servers: Servers{
174+
&Server{
175+
URL: "http://example.com/b/{var2}/a",
176+
Variables: map[string]*ServerVariable{
177+
"var2": {
178+
Default: "LLLLL",
179+
},
180+
},
181+
},
182+
&Server{
183+
URL: "https://example.com/b/{var1}/a",
184+
Variables: map[string]*ServerVariable{
185+
"var1": {
186+
Default: "lllll",
187+
},
188+
},
189+
},
190+
},
191+
expected: "/b/LLLLL/a",
192+
},
193+
} {
194+
t.Run(testcase.title, func(t *testing.T) {
195+
err := testcase.servers.Validate(context.Background())
196+
require.NoError(t, err)
197+
198+
got, err := testcase.servers.BasePath()
199+
require.NoError(t, err)
200+
require.Exactly(t, testcase.expected, got)
201+
})
202+
}
203+
}

0 commit comments

Comments
 (0)