From 0e6b74dde9455475fb60b47c80b375f754a56568 Mon Sep 17 00:00:00 2001 From: Dave Shanley Date: Mon, 29 Apr 2024 11:20:30 -0400 Subject: [PATCH] cleaned up panic in path params when schema is missing --- parameters/path_parameters.go | 254 +++++++++++++++++----------------- requests/validate_body.go | 2 +- 2 files changed, 129 insertions(+), 127 deletions(-) diff --git a/parameters/path_parameters.go b/parameters/path_parameters.go index 154890d..1d0032c 100644 --- a/parameters/path_parameters.go +++ b/parameters/path_parameters.go @@ -108,22 +108,45 @@ func (v *paramValidator) ValidatePathParams(request *http.Request) (bool, []*err } // for each type, check the value. - for typ := range sch.Type { + if sch != nil && sch.Type != nil { + for typ := range sch.Type { - switch sch.Type[typ] { - case helpers.String: + switch sch.Type[typ] { + case helpers.String: - // TODO: label and matrix style validation + // TODO: label and matrix style validation - // check if the param is within the enum - if sch.Enum != nil { - enumCheck(paramValue) - break - } - validationErrors = append(validationErrors, - ValidateSingleParameterSchema( + // check if the param is within the enum + if sch.Enum != nil { + enumCheck(paramValue) + break + } + validationErrors = append(validationErrors, + ValidateSingleParameterSchema( + sch, + paramValue, + "Path parameter", + "The path parameter", + p.Name, + helpers.ParameterValidation, + helpers.ParameterValidationPath, + )...) + + case helpers.Integer, helpers.Number: + // simple use case is already handled in find param. + rawParamValue, paramValueParsed, err := v.resolveNumber(sch, p, isLabel, isMatrix, paramValue) + if err != nil { + validationErrors = append(validationErrors, err...) + break + } + // check if the param is within the enum + if sch.Enum != nil { + enumCheck(rawParamValue) + break + } + validationErrors = append(validationErrors, ValidateSingleParameterSchema( sch, - paramValue, + paramValueParsed, "Path parameter", "The path parameter", p.Name, @@ -131,140 +154,119 @@ func (v *paramValidator) ValidatePathParams(request *http.Request) (bool, []*err helpers.ParameterValidationPath, )...) - case helpers.Integer, helpers.Number: - // simple use case is already handled in find param. - rawParamValue, paramValueParsed, err := v.resolveNumber(sch, p, isLabel, isMatrix, paramValue) - if err != nil { - validationErrors = append(validationErrors, err...) - break - } - // check if the param is within the enum - if sch.Enum != nil { - enumCheck(rawParamValue) - break - } - validationErrors = append(validationErrors, ValidateSingleParameterSchema( - sch, - paramValueParsed, - "Path parameter", - "The path parameter", - p.Name, - helpers.ParameterValidation, - helpers.ParameterValidationPath, - )...) - - case helpers.Boolean: - if isLabel && p.Style == helpers.LabelStyle { - if _, err := strconv.ParseFloat(paramValue[1:], 64); err != nil { - validationErrors = append(validationErrors, - errors.IncorrectPathParamBool(p, paramValue[1:], sch)) - } - } - if isSimple { - if _, err := strconv.ParseBool(paramValue); err != nil { - validationErrors = append(validationErrors, - errors.IncorrectPathParamBool(p, paramValue, sch)) - } - } - if isMatrix && p.Style == helpers.MatrixStyle { - // strip off the colon and the parameter name - paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) - if _, err := strconv.ParseBool(paramValue); err != nil { - validationErrors = append(validationErrors, - errors.IncorrectPathParamBool(p, paramValue, sch)) - } - } - case helpers.Object: - var encodedObject interface{} - - if p.IsDefaultPathEncoding() { - encodedObject = helpers.ConstructMapFromCSV(paramValue) - } else { - switch p.Style { - case helpers.LabelStyle: - if !p.IsExploded() { - encodedObject = helpers.ConstructMapFromCSV(paramValue[1:]) - } else { - encodedObject = helpers.ConstructKVFromLabelEncoding(paramValue) + case helpers.Boolean: + if isLabel && p.Style == helpers.LabelStyle { + if _, err := strconv.ParseFloat(paramValue[1:], 64); err != nil { + validationErrors = append(validationErrors, + errors.IncorrectPathParamBool(p, paramValue[1:], sch)) } - case helpers.MatrixStyle: - if !p.IsExploded() { - paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) - encodedObject = helpers.ConstructMapFromCSV(paramValue) - } else { - paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) - encodedObject = helpers.ConstructKVFromMatrixCSV(paramValue) + } + if isSimple { + if _, err := strconv.ParseBool(paramValue); err != nil { + validationErrors = append(validationErrors, + errors.IncorrectPathParamBool(p, paramValue, sch)) } - default: - if p.IsExploded() { - encodedObject = helpers.ConstructKVFromCSV(paramValue) + } + if isMatrix && p.Style == helpers.MatrixStyle { + // strip off the colon and the parameter name + paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) + if _, err := strconv.ParseBool(paramValue); err != nil { + validationErrors = append(validationErrors, + errors.IncorrectPathParamBool(p, paramValue, sch)) } } - } - // if a schema was extracted - if sch != nil { - validationErrors = append(validationErrors, - ValidateParameterSchema(sch, - encodedObject, - "", - "Path parameter", - "The path parameter", - p.Name, - helpers.ParameterValidation, - helpers.ParameterValidationPath)...) - } + case helpers.Object: + var encodedObject interface{} - case helpers.Array: - - // extract the items schema in order to validate the array items. - if sch.Items != nil && sch.Items.IsA() { - iSch := sch.Items.A.Schema() - for n := range iSch.Type { - // determine how to explode the array - var arrayValues []string - if isSimple { - arrayValues = strings.Split(paramValue, helpers.Comma) - } - if isLabel { + if p.IsDefaultPathEncoding() { + encodedObject = helpers.ConstructMapFromCSV(paramValue) + } else { + switch p.Style { + case helpers.LabelStyle: if !p.IsExploded() { - arrayValues = strings.Split(paramValue[1:], helpers.Comma) + encodedObject = helpers.ConstructMapFromCSV(paramValue[1:]) } else { - arrayValues = strings.Split(paramValue[1:], helpers.Period) + encodedObject = helpers.ConstructKVFromLabelEncoding(paramValue) } - } - if isMatrix { + case helpers.MatrixStyle: if !p.IsExploded() { paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) - arrayValues = strings.Split(paramValue, helpers.Comma) + encodedObject = helpers.ConstructMapFromCSV(paramValue) } else { - paramValue = strings.ReplaceAll(paramValue[1:], fmt.Sprintf("%s=", p.Name), "") - arrayValues = strings.Split(paramValue, helpers.SemiColon) + paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) + encodedObject = helpers.ConstructKVFromMatrixCSV(paramValue) + } + default: + if p.IsExploded() { + encodedObject = helpers.ConstructKVFromCSV(paramValue) } } - switch iSch.Type[n] { - case helpers.Integer, helpers.Number: - for pv := range arrayValues { - if _, err := strconv.ParseFloat(arrayValues[pv], 64); err != nil { - validationErrors = append(validationErrors, - errors.IncorrectPathParamArrayNumber(p, arrayValues[pv], sch, iSch)) + } + // if a schema was extracted + if sch != nil { + validationErrors = append(validationErrors, + ValidateParameterSchema(sch, + encodedObject, + "", + "Path parameter", + "The path parameter", + p.Name, + helpers.ParameterValidation, + helpers.ParameterValidationPath)...) + } + + case helpers.Array: + + // extract the items schema in order to validate the array items. + if sch.Items != nil && sch.Items.IsA() { + iSch := sch.Items.A.Schema() + for n := range iSch.Type { + // determine how to explode the array + var arrayValues []string + if isSimple { + arrayValues = strings.Split(paramValue, helpers.Comma) + } + if isLabel { + if !p.IsExploded() { + arrayValues = strings.Split(paramValue[1:], helpers.Comma) + } else { + arrayValues = strings.Split(paramValue[1:], helpers.Period) + } + } + if isMatrix { + if !p.IsExploded() { + paramValue = strings.Replace(paramValue[1:], fmt.Sprintf("%s=", p.Name), "", 1) + arrayValues = strings.Split(paramValue, helpers.Comma) + } else { + paramValue = strings.ReplaceAll(paramValue[1:], fmt.Sprintf("%s=", p.Name), "") + arrayValues = strings.Split(paramValue, helpers.SemiColon) } } - case helpers.Boolean: - for pv := range arrayValues { - bc := len(validationErrors) - if _, err := strconv.ParseBool(arrayValues[pv]); err != nil { - validationErrors = append(validationErrors, - errors.IncorrectPathParamArrayBoolean(p, arrayValues[pv], sch, iSch)) - continue + switch iSch.Type[n] { + case helpers.Integer, helpers.Number: + for pv := range arrayValues { + if _, err := strconv.ParseFloat(arrayValues[pv], 64); err != nil { + validationErrors = append(validationErrors, + errors.IncorrectPathParamArrayNumber(p, arrayValues[pv], sch, iSch)) + } } - if len(validationErrors) == bc { - // ParseBool will parse 0 or 1 as false/true to we - // need to catch this edge case. - if arrayValues[pv] == "0" || arrayValues[pv] == "1" { + case helpers.Boolean: + for pv := range arrayValues { + bc := len(validationErrors) + if _, err := strconv.ParseBool(arrayValues[pv]); err != nil { validationErrors = append(validationErrors, errors.IncorrectPathParamArrayBoolean(p, arrayValues[pv], sch, iSch)) continue } + if len(validationErrors) == bc { + // ParseBool will parse 0 or 1 as false/true to we + // need to catch this edge case. + if arrayValues[pv] == "0" || arrayValues[pv] == "1" { + validationErrors = append(validationErrors, + errors.IncorrectPathParamArrayBoolean(p, arrayValues[pv], sch, iSch)) + continue + } + } } } } diff --git a/requests/validate_body.go b/requests/validate_body.go index 4667d01..c13294d 100644 --- a/requests/validate_body.go +++ b/requests/validate_body.go @@ -44,7 +44,7 @@ func (v *requestBodyValidator) ValidateRequestBody(request *http.Request) (bool, required = *operation.RequestBody.Required } if contentType == "" { - if !required{ + if !required { // request body is not required, the validation stop there. return true, nil }