diff --git a/openapi3filter/issue641_test.go b/openapi3filter/issue641_test.go new file mode 100644 index 000000000..3e0bba22e --- /dev/null +++ b/openapi3filter/issue641_test.go @@ -0,0 +1,109 @@ +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 TestIssue641(t *testing.T) { + + anyOfSpec := ` +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: false + schema: + anyOf: + - pattern: "^[0-9]{1,4}$" + - pattern: "^[0-9]{1,4}$" + type: string + responses: + '200': + description: Successful response +`[1:] + + allOfSpec := strings.ReplaceAll(anyOfSpec, "anyOf", "allOf") + + tests := []struct { + name string + spec string + req string + errStr string + }{ + + { + name: "success anyof pattern", + spec: anyOfSpec, + req: "/items?test=51", + }, + { + name: "failed anyof pattern", + spec: anyOfSpec, + req: "/items?test=999999", + errStr: `parameter "test" in query has an error: Doesn't match schema "anyOf"`, + }, + + { + name: "success allof pattern", + spec: allOfSpec, + req: `/items?test=51`, + }, + { + name: "failed allof pattern", + spec: allOfSpec, + req: `/items?test=999999`, + errStr: `parameter "test" in query has an error: string doesn't match the regular expression`, + }, + } + + 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) + } + }, + ) + } +} diff --git a/openapi3filter/req_resp_decoder.go b/openapi3filter/req_resp_decoder.go index ca8194432..f98a51048 100644 --- a/openapi3filter/req_resp_decoder.go +++ b/openapi3filter/req_resp_decoder.go @@ -334,6 +334,9 @@ func decodeValue(dec valueDecoder, param string, sm *openapi3.SerializationMetho case *pathParamDecoder: _, found = vDecoder.pathParams[param] case *urlValuesDecoder: + if schema.Value.Pattern != "" { + return dec.DecodePrimitive(param, sm, schema) + } _, found = vDecoder.values[param] case *headerParamDecoder: _, found = vDecoder.header[param] @@ -500,6 +503,10 @@ func (d *urlValuesDecoder) DecodePrimitive(param string, sm *openapi3.Serializat // HTTP request does not contain a value of the target query parameter. return nil, ok, nil } + + if schema.Value.Type == "" && schema.Value.Pattern != "" { + return values[0], ok, nil + } val, err := parsePrimitive(values[0], schema) return val, ok, err }