Skip to content

Commit df9133b

Browse files
authored
fix: query param pattern (#665)
1 parent 8165c43 commit df9133b

2 files changed

Lines changed: 116 additions & 0 deletions

File tree

openapi3filter/issue641_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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 TestIssue641(t *testing.T) {
16+
17+
anyOfSpec := `
18+
openapi: 3.0.0
19+
info:
20+
version: 1.0.0
21+
title: Sample API
22+
paths:
23+
/items:
24+
get:
25+
description: Returns a list of stuff
26+
parameters:
27+
- description: test object
28+
explode: false
29+
in: query
30+
name: test
31+
required: false
32+
schema:
33+
anyOf:
34+
- pattern: "^[0-9]{1,4}$"
35+
- pattern: "^[0-9]{1,4}$"
36+
type: string
37+
responses:
38+
'200':
39+
description: Successful response
40+
`[1:]
41+
42+
allOfSpec := strings.ReplaceAll(anyOfSpec, "anyOf", "allOf")
43+
44+
tests := []struct {
45+
name string
46+
spec string
47+
req string
48+
errStr string
49+
}{
50+
51+
{
52+
name: "success anyof pattern",
53+
spec: anyOfSpec,
54+
req: "/items?test=51",
55+
},
56+
{
57+
name: "failed anyof pattern",
58+
spec: anyOfSpec,
59+
req: "/items?test=999999",
60+
errStr: `parameter "test" in query has an error: Doesn't match schema "anyOf"`,
61+
},
62+
63+
{
64+
name: "success allof pattern",
65+
spec: allOfSpec,
66+
req: `/items?test=51`,
67+
},
68+
{
69+
name: "failed allof pattern",
70+
spec: allOfSpec,
71+
req: `/items?test=999999`,
72+
errStr: `parameter "test" in query has an error: string doesn't match the regular expression`,
73+
},
74+
}
75+
76+
for _, testcase := range tests {
77+
t.Run(testcase.name, func(t *testing.T) {
78+
loader := openapi3.NewLoader()
79+
ctx := loader.Context
80+
81+
doc, err := loader.LoadFromData([]byte(testcase.spec))
82+
require.NoError(t, err)
83+
84+
err = doc.Validate(ctx)
85+
require.NoError(t, err)
86+
87+
router, err := gorillamux.NewRouter(doc)
88+
require.NoError(t, err)
89+
httpReq, err := http.NewRequest(http.MethodGet, testcase.req, nil)
90+
require.NoError(t, err)
91+
92+
route, pathParams, err := router.FindRoute(httpReq)
93+
require.NoError(t, err)
94+
95+
requestValidationInput := &openapi3filter.RequestValidationInput{
96+
Request: httpReq,
97+
PathParams: pathParams,
98+
Route: route,
99+
}
100+
err = openapi3filter.ValidateRequest(ctx, requestValidationInput)
101+
if testcase.errStr == "" {
102+
require.NoError(t, err)
103+
} else {
104+
require.Contains(t, err.Error(), testcase.errStr)
105+
}
106+
},
107+
)
108+
}
109+
}

openapi3filter/req_resp_decoder.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMetho
334334
case *pathParamDecoder:
335335
_, found = vDecoder.pathParams[param]
336336
case *urlValuesDecoder:
337+
if schema.Value.Pattern != "" {
338+
return dec.DecodePrimitive(param, sm, schema)
339+
}
337340
_, found = vDecoder.values[param]
338341
case *headerParamDecoder:
339342
_, found = vDecoder.header[param]
@@ -500,6 +503,10 @@ func (d *urlValuesDecoder) DecodePrimitive(param string, sm *openapi3.Serializat
500503
// HTTP request does not contain a value of the target query parameter.
501504
return nil, ok, nil
502505
}
506+
507+
if schema.Value.Type == "" && schema.Value.Pattern != "" {
508+
return values[0], ok, nil
509+
}
503510
val, err := parsePrimitive(values[0], schema)
504511
return val, ok, err
505512
}

0 commit comments

Comments
 (0)