Skip to content

Commit b8c06e7

Browse files
authored
openapi3filter: fix oneOF validation in query params (#790)
1 parent 1b54b4d commit b8c06e7

File tree

3 files changed

+127
-10
lines changed

3 files changed

+127
-10
lines changed

openapi3filter/issue789_test.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package openapi3filter_test
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/getkin/kin-openapi/openapi3"
11+
"github.com/getkin/kin-openapi/openapi3filter"
12+
"github.com/getkin/kin-openapi/routers/gorillamux"
13+
)
14+
15+
func TestIssue789(t *testing.T) {
16+
anyOfArraySpec := `
17+
openapi: 3.0.0
18+
info:
19+
version: 1.0.0
20+
title: Sample API
21+
paths:
22+
/items:
23+
get:
24+
description: Returns a list of stuff
25+
parameters:
26+
- description: test object
27+
explode: false
28+
in: query
29+
name: test
30+
required: true
31+
schema:
32+
type: string
33+
anyOf:
34+
- pattern: '\babc\b'
35+
- pattern: '\bfoo\b'
36+
- pattern: '\bbar\b'
37+
responses:
38+
'200':
39+
description: Successful response
40+
`[1:]
41+
42+
oneOfArraySpec := strings.ReplaceAll(anyOfArraySpec, "anyOf", "oneOf")
43+
44+
allOfArraySpec := strings.ReplaceAll(anyOfArraySpec, "anyOf", "allOf")
45+
46+
tests := []struct {
47+
name string
48+
spec string
49+
req string
50+
errStr string
51+
}{
52+
{
53+
name: "success anyof string pattern match",
54+
spec: anyOfArraySpec,
55+
req: "/items?test=abc",
56+
},
57+
{
58+
name: "failed anyof string pattern match",
59+
spec: anyOfArraySpec,
60+
req: "/items?test=def",
61+
errStr: `parameter "test" in query has an error: doesn't match any schema from "anyOf"`,
62+
},
63+
{
64+
name: "success allof object array",
65+
spec: allOfArraySpec,
66+
req: `/items?test=abc foo bar`,
67+
},
68+
{
69+
name: "failed allof object array",
70+
spec: allOfArraySpec,
71+
req: `/items?test=foo`,
72+
errStr: `parameter "test" in query has an error: string doesn't match the regular expression`,
73+
},
74+
{
75+
name: "success oneof string pattern match",
76+
spec: oneOfArraySpec,
77+
req: `/items?test=foo`,
78+
},
79+
{
80+
name: "failed oneof string pattern match",
81+
spec: oneOfArraySpec,
82+
req: `/items?test=def`,
83+
errStr: `parameter "test" in query has an error: doesn't match schema due to: string doesn't match the regular expression`,
84+
},
85+
{
86+
name: "failed oneof string pattern match",
87+
spec: oneOfArraySpec,
88+
req: `/items?test=foo bar`,
89+
errStr: `parameter "test" in query has an error: input matches more than one oneOf schemas`,
90+
},
91+
}
92+
93+
for _, testcase := range tests {
94+
t.Run(testcase.name, func(t *testing.T) {
95+
loader := openapi3.NewLoader()
96+
ctx := loader.Context
97+
98+
doc, err := loader.LoadFromData([]byte(testcase.spec))
99+
require.NoError(t, err)
100+
101+
err = doc.Validate(ctx)
102+
require.NoError(t, err)
103+
104+
router, err := gorillamux.NewRouter(doc)
105+
require.NoError(t, err)
106+
httpReq, err := http.NewRequest(http.MethodGet, testcase.req, nil)
107+
require.NoError(t, err)
108+
109+
route, pathParams, err := router.FindRoute(httpReq)
110+
require.NoError(t, err)
111+
112+
requestValidationInput := &openapi3filter.RequestValidationInput{
113+
Request: httpReq,
114+
PathParams: pathParams,
115+
Route: route,
116+
}
117+
err = openapi3filter.ValidateRequest(ctx, requestValidationInput)
118+
if testcase.errStr == "" {
119+
require.NoError(t, err)
120+
} else {
121+
require.Contains(t, err.Error(), testcase.errStr)
122+
}
123+
},
124+
)
125+
}
126+
}

openapi3filter/req_resp_decoder.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,8 @@ func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMetho
301301
isMatched++
302302
}
303303
}
304-
if isMatched == 1 {
304+
if isMatched >= 1 {
305305
return value, found, nil
306-
} else if isMatched > 1 {
307-
return nil, found, fmt.Errorf("decoding oneOf failed: %d schemas matched", isMatched)
308306
}
309307
if required {
310308
return nil, found, fmt.Errorf("decoding oneOf failed: %q is required", param)

openapi3filter/validation_test.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,6 @@ func TestFilter(t *testing.T) {
268268
err = expect(req, resp)
269269
require.IsType(t, &RequestError{}, err)
270270

271-
req = ExampleRequest{
272-
Method: "POST",
273-
URL: "http://example.com/api/prefix/v/suffix?queryArgOneOf=567",
274-
}
275-
err = expect(req, resp)
276-
require.IsType(t, &RequestError{}, err)
277-
278271
req = ExampleRequest{
279272
Method: "POST",
280273
URL: "http://example.com/api/prefix/v/suffix?queryArgOneOf=2017-12-31T11:59:59",

0 commit comments

Comments
 (0)