From 0f63dd0975c259c556e935c1ccbc702d7b083c2d Mon Sep 17 00:00:00 2001 From: Naoyoshi Kobayashi Date: Fri, 8 Dec 2023 17:27:52 +0900 Subject: [PATCH 1/5] feat: support default value binding with allOfSchema --- openapi3filter/validate_request.go | 45 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/openapi3filter/validate_request.go b/openapi3filter/validate_request.go index db3b07532..793cc8048 100644 --- a/openapi3filter/validate_request.go +++ b/openapi3filter/validate_request.go @@ -136,24 +136,35 @@ func ValidateParameter(ctx context.Context, input *RequestValidationInput, param } // Set default value if needed - if !options.SkipSettingDefaults && value == nil && schema != nil && schema.Default != nil { + if !options.SkipSettingDefaults && value == nil && schema != nil { value = schema.Default - req := input.Request - switch parameter.In { - case openapi3.ParameterInPath: - // Path parameters are required. - // Next check `parameter.Required && !found` will catch this. - case openapi3.ParameterInQuery: - q := req.URL.Query() - q.Add(parameter.Name, fmt.Sprintf("%v", value)) - req.URL.RawQuery = q.Encode() - case openapi3.ParameterInHeader: - req.Header.Add(parameter.Name, fmt.Sprintf("%v", value)) - case openapi3.ParameterInCookie: - req.AddCookie(&http.Cookie{ - Name: parameter.Name, - Value: fmt.Sprintf("%v", value), - }) + if schema.AllOf != nil { + for _, subSchema := range schema.AllOf { + if subSchema.Value.Default != nil { + value = subSchema.Value.Default + break + } + } + } + + if value != nil { + req := input.Request + switch parameter.In { + case openapi3.ParameterInPath: + // Path parameters are required. + // Next check `parameter.Required && !found` will catch this. + case openapi3.ParameterInQuery: + q := req.URL.Query() + q.Add(parameter.Name, fmt.Sprintf("%v", value)) + req.URL.RawQuery = q.Encode() + case openapi3.ParameterInHeader: + req.Header.Add(parameter.Name, fmt.Sprintf("%v", value)) + case openapi3.ParameterInCookie: + req.AddCookie(&http.Cookie{ + Name: parameter.Name, + Value: fmt.Sprintf("%v", value), + }) + } } } From 7ee001eccc4fb7d705e5c997b3b64287765d8ff3 Mon Sep 17 00:00:00 2001 From: Naoyoshi Kobayashi Date: Sat, 9 Dec 2023 11:56:21 +0900 Subject: [PATCH 2/5] test: add regression tests --- openapi3filter/issue884_test.go | 112 ++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 openapi3filter/issue884_test.go diff --git a/openapi3filter/issue884_test.go b/openapi3filter/issue884_test.go new file mode 100644 index 000000000..0f692154d --- /dev/null +++ b/openapi3filter/issue884_test.go @@ -0,0 +1,112 @@ +package openapi3filter + +import ( + "net/http" + "net/url" + "testing" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers/gorillamux" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIssue884(t *testing.T) { + loader := openapi3.NewLoader() + ctx := loader.Context + spec := ` + openapi: 3.0.0 + info: + version: 1.0.0 + title: Sample API + components: + schemas: + TaskSortEnum: + enum: + - createdAt + - -createdAt + - updatedAt + - -updatedAt + paths: + /tasks: + get: + operationId: ListTask + parameters: + - in: query + name: withDefault + schema: + allOf: + - $ref: '#/components/schemas/TaskSortEnum' + - default: -createdAt + - in: query + name: withoutDefault + schema: + allOf: + - $ref: '#/components/schemas/TaskSortEnum' + - in: query + name: withManyDefaults + schema: + allOf: + - default: -updatedAt + - $ref: '#/components/schemas/TaskSortEnum' + - default: -createdAt + responses: + '200': + description: Successful response + `[1:] + + doc, err := loader.LoadFromData([]byte(spec)) + require.NoError(t, err) + + err = doc.Validate(ctx) + require.NoError(t, err) + + router, err := gorillamux.NewRouter(doc) + require.NoError(t, err) + + tests := []struct { + name string + options *Options + expectedQuery url.Values + }{ + { + name: "no defaults are added to requests", + options: &Options{ + SkipSettingDefaults: true, + }, + expectedQuery: url.Values{}, + }, + + { + name: "defaults are added to requests", + expectedQuery: url.Values{ + "withDefault": []string{"-createdAt"}, + "withManyDefaults": []string{"-updatedAt"}, // first default is win + }, + }, + } + + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + httpReq, err := http.NewRequest(http.MethodGet, "/tasks", nil) + require.NoError(t, err) + httpReq.Header.Set("Content-Type", "application/json") + require.NoError(t, err) + + route, pathParams, err := router.FindRoute(httpReq) + require.NoError(t, err) + + requestValidationInput := &RequestValidationInput{ + Request: httpReq, + PathParams: pathParams, + Route: route, + Options: testcase.options, + } + err = ValidateRequest(ctx, requestValidationInput) + require.NoError(t, err) + + q := httpReq.URL.Query() + assert.Equal(t, testcase.expectedQuery, q) + }) + } +} From ac1f462205733927a9fd9c6efe612b945baffd4c Mon Sep 17 00:00:00 2001 From: Naoyoshi Kobayashi Date: Sat, 9 Dec 2023 12:02:40 +0900 Subject: [PATCH 3/5] refactor: simplify --- openapi3filter/validate_request.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/openapi3filter/validate_request.go b/openapi3filter/validate_request.go index 793cc8048..1138740d4 100644 --- a/openapi3filter/validate_request.go +++ b/openapi3filter/validate_request.go @@ -138,12 +138,10 @@ func ValidateParameter(ctx context.Context, input *RequestValidationInput, param // Set default value if needed if !options.SkipSettingDefaults && value == nil && schema != nil { value = schema.Default - if schema.AllOf != nil { - for _, subSchema := range schema.AllOf { - if subSchema.Value.Default != nil { - value = subSchema.Value.Default - break - } + for _, subSchema := range schema.AllOf { + if subSchema.Value.Default != nil { + value = subSchema.Value.Default + break } } From 10d09ae2baa85255d8244a7b68f0d033b90864f1 Mon Sep 17 00:00:00 2001 From: Naoyoshi Kobayashi Date: Sat, 9 Dec 2023 12:07:04 +0900 Subject: [PATCH 4/5] style: fmt with goimports-reviser --- openapi3filter/issue884_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openapi3filter/issue884_test.go b/openapi3filter/issue884_test.go index 0f692154d..ea6e461c0 100644 --- a/openapi3filter/issue884_test.go +++ b/openapi3filter/issue884_test.go @@ -5,10 +5,11 @@ import ( "net/url" "testing" - "github.com/getkin/kin-openapi/openapi3" - "github.com/getkin/kin-openapi/routers/gorillamux" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers/gorillamux" ) func TestIssue884(t *testing.T) { From fba4f1cd1932d7160d7fd6f3d1f39574a310af52 Mon Sep 17 00:00:00 2001 From: Naoyoshi Kobayashi Date: Sat, 9 Dec 2023 12:29:04 +0900 Subject: [PATCH 5/5] add comments --- openapi3filter/validate_request.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi3filter/validate_request.go b/openapi3filter/validate_request.go index 1138740d4..8bc4f2a4b 100644 --- a/openapi3filter/validate_request.go +++ b/openapi3filter/validate_request.go @@ -141,7 +141,7 @@ func ValidateParameter(ctx context.Context, input *RequestValidationInput, param for _, subSchema := range schema.AllOf { if subSchema.Value.Default != nil { value = subSchema.Value.Default - break + break // This is not a validation of the schema itself, so use the first default value. } }