diff --git a/openapi3filter/issue639_test.go b/openapi3filter/issue639_test.go new file mode 100644 index 000000000..2caf1bd14 --- /dev/null +++ b/openapi3filter/issue639_test.go @@ -0,0 +1,100 @@ +package openapi3filter + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/routers/gorillamux" +) + +func TestIssue639(t *testing.T) { + loader := openapi3.NewLoader() + ctx := loader.Context + spec := ` + openapi: 3.0.0 + info: + version: 1.0.0 + title: Sample API + paths: + /items: + put: + requestBody: + content: + application/json: + schema: + properties: + testWithdefault: + default: false + type: boolean + testNoDefault: + type: boolean + type: object + responses: + '200': + description: Successful respons +`[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 + expectedDefaultVal interface{} + }{ + { + name: "no defaults are added to requests", + options: &Options{ + SkipSettingDefaults: true, + }, + expectedDefaultVal: nil, + }, + + { + name: "defaults are added to requests", + expectedDefaultVal: false, + }, + } + + for _, testcase := range tests { + t.Run(testcase.name, func(t *testing.T) { + body := "{\"testNoDefault\": true}" + httpReq, err := http.NewRequest(http.MethodPut, "/items", strings.NewReader(body)) + 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) + bodyAfterValidation, err := ioutil.ReadAll(httpReq.Body) + require.NoError(t, err) + + raw := map[string]interface{}{} + err = json.Unmarshal(bodyAfterValidation, &raw) + require.NoError(t, err) + require.Equal(t, testcase.expectedDefaultVal, + raw["testWithdefault"], "default value must not be included") + }) + } +} diff --git a/openapi3filter/options.go b/openapi3filter/options.go index 1622339e2..14843dd1b 100644 --- a/openapi3filter/options.go +++ b/openapi3filter/options.go @@ -21,4 +21,8 @@ type Options struct { // See NoopAuthenticationFunc AuthenticationFunc AuthenticationFunc + + // Indicates whether default values are set in the + // request. If true, then they are not set + SkipSettingDefaults bool } diff --git a/openapi3filter/validate_request.go b/openapi3filter/validate_request.go index 4b0bd3413..70b8e8d0a 100644 --- a/openapi3filter/validate_request.go +++ b/openapi3filter/validate_request.go @@ -258,7 +258,9 @@ func ValidateRequestBody(ctx context.Context, input *RequestValidationInput, req defaultsSet := false opts := make([]openapi3.SchemaValidationOption, 0, 3) // 3 potential opts here opts = append(opts, openapi3.VisitAsRequest()) - opts = append(opts, openapi3.DefaultsSet(func() { defaultsSet = true })) + if !options.SkipSettingDefaults { + opts = append(opts, openapi3.DefaultsSet(func() { defaultsSet = true })) + } if options.MultiError { opts = append(opts, openapi3.MultiErrors()) }