Skip to content

Commit

Permalink
openapi3filter: fix oneOF validation in query params (#790)
Browse files Browse the repository at this point in the history
  • Loading branch information
ju-zp committed May 18, 2023
1 parent 1b54b4d commit b8c06e7
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 10 deletions.
126 changes: 126 additions & 0 deletions openapi3filter/issue789_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package openapi3filter_test

import (
"net/http"
"strings"
"testing"

"github.com/stretchr/testify/require"

"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
"github.com/getkin/kin-openapi/routers/gorillamux"
)

func TestIssue789(t *testing.T) {
anyOfArraySpec := `
openapi: 3.0.0
info:
version: 1.0.0
title: Sample API
paths:
/items:
get:
description: Returns a list of stuff
parameters:
- description: test object
explode: false
in: query
name: test
required: true
schema:
type: string
anyOf:
- pattern: '\babc\b'
- pattern: '\bfoo\b'
- pattern: '\bbar\b'
responses:
'200':
description: Successful response
`[1:]

oneOfArraySpec := strings.ReplaceAll(anyOfArraySpec, "anyOf", "oneOf")

allOfArraySpec := strings.ReplaceAll(anyOfArraySpec, "anyOf", "allOf")

tests := []struct {
name string
spec string
req string
errStr string
}{
{
name: "success anyof string pattern match",
spec: anyOfArraySpec,
req: "/items?test=abc",
},
{
name: "failed anyof string pattern match",
spec: anyOfArraySpec,
req: "/items?test=def",
errStr: `parameter "test" in query has an error: doesn't match any schema from "anyOf"`,
},
{
name: "success allof object array",
spec: allOfArraySpec,
req: `/items?test=abc foo bar`,
},
{
name: "failed allof object array",
spec: allOfArraySpec,
req: `/items?test=foo`,
errStr: `parameter "test" in query has an error: string doesn't match the regular expression`,
},
{
name: "success oneof string pattern match",
spec: oneOfArraySpec,
req: `/items?test=foo`,
},
{
name: "failed oneof string pattern match",
spec: oneOfArraySpec,
req: `/items?test=def`,
errStr: `parameter "test" in query has an error: doesn't match schema due to: string doesn't match the regular expression`,
},
{
name: "failed oneof string pattern match",
spec: oneOfArraySpec,
req: `/items?test=foo bar`,
errStr: `parameter "test" in query has an error: input matches more than one oneOf schemas`,
},
}

for _, testcase := range tests {
t.Run(testcase.name, func(t *testing.T) {
loader := openapi3.NewLoader()
ctx := loader.Context

doc, err := loader.LoadFromData([]byte(testcase.spec))
require.NoError(t, err)

err = doc.Validate(ctx)
require.NoError(t, err)

router, err := gorillamux.NewRouter(doc)
require.NoError(t, err)
httpReq, err := http.NewRequest(http.MethodGet, testcase.req, nil)
require.NoError(t, err)

route, pathParams, err := router.FindRoute(httpReq)
require.NoError(t, err)

requestValidationInput := &openapi3filter.RequestValidationInput{
Request: httpReq,
PathParams: pathParams,
Route: route,
}
err = openapi3filter.ValidateRequest(ctx, requestValidationInput)
if testcase.errStr == "" {
require.NoError(t, err)
} else {
require.Contains(t, err.Error(), testcase.errStr)
}
},
)
}
}
4 changes: 1 addition & 3 deletions openapi3filter/req_resp_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,10 +301,8 @@ func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMetho
isMatched++
}
}
if isMatched == 1 {
if isMatched >= 1 {
return value, found, nil
} else if isMatched > 1 {
return nil, found, fmt.Errorf("decoding oneOf failed: %d schemas matched", isMatched)
}
if required {
return nil, found, fmt.Errorf("decoding oneOf failed: %q is required", param)
Expand Down
7 changes: 0 additions & 7 deletions openapi3filter/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,6 @@ func TestFilter(t *testing.T) {
err = expect(req, resp)
require.IsType(t, &RequestError{}, err)

req = ExampleRequest{
Method: "POST",
URL: "http://example.com/api/prefix/v/suffix?queryArgOneOf=567",
}
err = expect(req, resp)
require.IsType(t, &RequestError{}, err)

req = ExampleRequest{
Method: "POST",
URL: "http://example.com/api/prefix/v/suffix?queryArgOneOf=2017-12-31T11:59:59",
Expand Down

0 comments on commit b8c06e7

Please sign in to comment.