diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml new file mode 100644 index 000000000..e1f8d1242 --- /dev/null +++ b/.github/workflows/shellcheck.yml @@ -0,0 +1,18 @@ +name: ShellCheck + +on: + push: + pull_request: + +jobs: + shellcheck: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Run shellcheck + uses: ludeeus/action-shellcheck@1.1.0 + with: + check_together: 'yes' + severity: error diff --git a/.github/workflows/suite.sh b/.github/workflows/suite.sh new file mode 100755 index 000000000..057e5295f --- /dev/null +++ b/.github/workflows/suite.sh @@ -0,0 +1,970 @@ +#!/bin/bash -eu + +set -o pipefail + +OAI_COMMIT=${OAI_COMMIT:-157a4c81ae537ef793b2bee368bc00d88b461de8} # On 2022-10-17 +OAI_SLUG=OAI-OpenAPI-Specification +OAI_DIR=$OAI_SLUG-${OAI_COMMIT:0:7}/examples + +if ! [[ -d $OAI_DIR ]]; then + curl -fSLo $OAI_SLUG.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"$OAI_COMMIT" + tar zxf $OAI_SLUG.tar.gz + rm $OAI_SLUG.tar.gz +fi + +APISGURU_COMMIT=${APISGURU_COMMIT:-226773819e337e6c413d1be91b26b33111211768} # On 2022-10-17 +APISGURU_SLUG=APIs-guru-openapi-directory +APISGURU_DIR=$APISGURU_SLUG-${APISGURU_COMMIT:0:7}/APIs + +if ! [[ -d $APISGURU_DIR ]]; then + curl -fSLo $APISGURU_SLUG.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"$APISGURU_COMMIT" + tar zxf $APISGURU_SLUG.tar.gz + rm $APISGURU_SLUG.tar.gz +fi + +cat <=1.15) + uses: actions/cache@v3 + with: + path: \${{ steps.go-cache-paths.outputs.go-mod }} + key: \${{ runner.os }}-go-\${{ matrix.go }}-mod-\${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: \${{ runner.os }}-go-\${{ matrix.go }}-suite-\${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d $OAI_DIR ]]; then + curl -fSLo $OAI_SLUG.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"$OAI_COMMIT" + tar zxf $OAI_SLUG.tar.gz + rm $OAI_SLUG.tar.gz + ls -lha $OAI_DIR + fi + if ! [[ -d $APISGURU_DIR ]]; then + curl -fSLo $APISGURU_SLUG.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"$APISGURU_COMMIT" + tar zxf $APISGURU_SLUG.tar.gz + rm $APISGURU_SLUG.tar.gz + ls -lha $APISGURU_DIR + fi + + - name: "$gen" + run: | + set -x + touch _ + while read -r file; do + echo "\$file" + go run ./cmd/validate $args "\$file" || echo "\$file" >_ + done < <($gen) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "ls OAI-OpenAPI-Specification-157a4c8/examples/v2.0/json/*.json OAI-OpenAPI-Specification-157a4c8/examples/v2.0/json/petstore-separate/spec/swagger.json" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(ls OAI-OpenAPI-Specification-157a4c8/examples/v2.0/json/*.json OAI-OpenAPI-Specification-157a4c8/examples/v2.0/json/petstore-separate/spec/swagger.json) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "ls OAI-OpenAPI-Specification-157a4c8/examples/v2.0/yaml/*.yaml OAI-OpenAPI-Specification-157a4c8/examples/v2.0/yaml/petstore-separate/spec/swagger.yaml" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(ls OAI-OpenAPI-Specification-157a4c8/examples/v2.0/yaml/*.yaml OAI-OpenAPI-Specification-157a4c8/examples/v2.0/yaml/petstore-separate/spec/swagger.yaml) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find OAI-OpenAPI-Specification-157a4c8/examples/v3.0 -type f | sort" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(find OAI-OpenAPI-Specification-157a4c8/examples/v3.0 -type f | sort) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find OAI-OpenAPI-Specification-157a4c8/examples/v3.1 -type f | sort" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(find OAI-OpenAPI-Specification-157a4c8/examples/v3.1 -type f | sort) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -F azure.com | grep -F network" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -F azure.com | grep -F network) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -F azure.com | grep -vF network" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -F azure.com | grep -vF network) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -vF azure.com" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate "$file" || echo "$file" >_ + done < <(find APIs-guru-openapi-directory-2267738/APIs -type f -name swagger.yaml | sort | grep -vF azure.com) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find APIs-guru-openapi-directory-2267738/APIs -type f -name openapi.yaml | sort | grep -F google" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate --patterns=false "$file" || echo "$file" >_ + done < <(find APIs-guru-openapi-directory-2267738/APIs -type f -name openapi.yaml | sort | grep -F google) + git add _ + + - name: Compare with expected results + run: | + cat >_ <=1.15) + uses: actions/cache@v3 + with: + path: ${{ steps.go-cache-paths.outputs.go-mod }} + key: ${{ runner.os }}-go-${{ matrix.go }}-mod-${{ hashFiles('**/go.sum') }} + + - uses: actions/checkout@v2 + + - name: Test suite fixtures cache + uses: actions/cache@v3 + with: + path: | + APIs-guru-openapi-directory-* + OAI-OpenAPI-Specification-* + key: ${{ runner.os }}-go-${{ matrix.go }}-suite-${{ hashFiles('.github/workflows/suite.sh') }} + + - name: Maybe fetch fixtures + run: | + pwd + if ! [[ -d OAI-OpenAPI-Specification-157a4c8/examples ]]; then + curl -fSLo OAI-OpenAPI-Specification.tar.gz https://github.com/OAI/OpenAPI-Specification/tarball/"157a4c81ae537ef793b2bee368bc00d88b461de8" + tar zxf OAI-OpenAPI-Specification.tar.gz + rm OAI-OpenAPI-Specification.tar.gz + ls -lha OAI-OpenAPI-Specification-157a4c8/examples + fi + if ! [[ -d APIs-guru-openapi-directory-2267738/APIs ]]; then + curl -fSLo APIs-guru-openapi-directory.tar.gz https://github.com/APIs-guru/openapi-directory/tarball/"226773819e337e6c413d1be91b26b33111211768" + tar zxf APIs-guru-openapi-directory.tar.gz + rm APIs-guru-openapi-directory.tar.gz + ls -lha APIs-guru-openapi-directory-2267738/APIs + fi + + - name: "find APIs-guru-openapi-directory-2267738/APIs -type f -name openapi.yaml | sort | grep -vF google" + run: | + set -x + touch _ + while read -r file; do + echo "$file" + go run ./cmd/validate --patterns=false "$file" || echo "$file" >_ + done < <(find APIs-guru-openapi-directory-2267738/APIs -type f -name openapi.yaml | sort | grep -vF google) + git add _ + + - name: Compare with expected results + run: | + cat >_ <\nGot: %+v\n", os.Args) + } + + data, err := os.ReadFile(filename) + if err != nil { + log.Fatal(err) + } + + var vd struct { + OpenAPI string `json:"openapi" yaml:"openapi"` + Swagger string `json:"swagger" yaml:"swagger"` + } + if err := yaml.Unmarshal(data, &vd); err != nil { + log.Fatal(err) + } + + switch { + case vd.OpenAPI == "3" || strings.HasPrefix(vd.OpenAPI, "3."): + loader := openapi3.NewLoader() + loader.IsExternalRefsAllowed = *ext + + doc, err := loader.LoadFromFile(filename) + if err != nil { + log.Fatal(err) + } + + var opts []openapi3.ValidationOption + if !*defaults { + opts = append(opts, openapi3.DisableSchemaDefaultsValidation()) + } + if !*examples { + opts = append(opts, openapi3.DisableExamplesValidation()) + } + if !*patterns { + opts = append(opts, openapi3.DisableSchemaPatternValidation()) + } + + if err = doc.Validate(loader.Context, opts...); err != nil { + log.Fatal(err) + } + + case vd.Swagger == "2" || strings.HasPrefix(vd.Swagger, "2."): + if *defaults != defaultDefaults { + log.Fatal("Flag --defaults is only for OpenAPIv3") + } + if *examples != defaultExamples { + log.Fatal("Flag --examples is only for OpenAPIv3") + } + if *ext != defaultExt { + log.Fatal("Flag --ext is only for OpenAPIv3") + } + if *patterns != defaultPatterns { + log.Fatal("Flag --patterns is only for OpenAPIv3") + } + + var doc openapi2.T + if err := yaml.Unmarshal(data, &doc); err != nil { + log.Fatal(err) + } + + default: + log.Fatal("Missing or incorrect 'openapi' or 'swagger' field") + } +} diff --git a/openapi3/media_type.go b/openapi3/media_type.go index 8e3fef7e6..090be7657 100644 --- a/openapi3/media_type.go +++ b/openapi3/media_type.go @@ -90,7 +90,7 @@ func (mediaType *MediaType) Validate(ctx context.Context, opts ...ValidationOpti return errors.New("example and examples are mutually exclusive") } - if vo := getValidationOptions(ctx); vo.ExamplesValidationDisabled { + if vo := getValidationOptions(ctx); vo.examplesValidationDisabled { return nil } diff --git a/openapi3/parameter.go b/openapi3/parameter.go index c55af474d..04e13b203 100644 --- a/openapi3/parameter.go +++ b/openapi3/parameter.go @@ -323,7 +323,7 @@ func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOpti return fmt.Errorf("parameter %q example and examples are mutually exclusive", parameter.Name) } - if vo := getValidationOptions(ctx); vo.ExamplesValidationDisabled { + if vo := getValidationOptions(ctx); vo.examplesValidationDisabled { return nil } if example := parameter.Example; example != nil { diff --git a/openapi3/request_body.go b/openapi3/request_body.go index baf7f81e8..f0d9e1ec2 100644 --- a/openapi3/request_body.go +++ b/openapi3/request_body.go @@ -112,7 +112,7 @@ func (requestBody *RequestBody) Validate(ctx context.Context, opts ...Validation return errors.New("content of the request body is required") } - if vo := getValidationOptions(ctx); !vo.ExamplesValidationDisabled { + if vo := getValidationOptions(ctx); !vo.examplesValidationDisabled { vo.examplesValidationAsReq, vo.examplesValidationAsRes = true, false } diff --git a/openapi3/response.go b/openapi3/response.go index eaf8e57f8..324f77ddc 100644 --- a/openapi3/response.go +++ b/openapi3/response.go @@ -119,7 +119,7 @@ func (response *Response) Validate(ctx context.Context, opts ...ValidationOption if response.Description == nil { return errors.New("a short description of the response is required") } - if vo := getValidationOptions(ctx); !vo.ExamplesValidationDisabled { + if vo := getValidationOptions(ctx); !vo.examplesValidationDisabled { vo.examplesValidationAsReq, vo.examplesValidationAsRes = false, true } diff --git a/openapi3/schema.go b/openapi3/schema.go index bbce46c7b..f2b4ea2c8 100644 --- a/openapi3/schema.go +++ b/openapi3/schema.go @@ -678,7 +678,7 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error) switch format { case "float", "double": default: - if validationOpts.SchemaFormatValidationEnabled { + if validationOpts.schemaFormatValidationEnabled { return unsupportedFormat(format) } } @@ -688,7 +688,7 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error) switch format { case "int32", "int64": default: - if validationOpts.SchemaFormatValidationEnabled { + if validationOpts.schemaFormatValidationEnabled { return unsupportedFormat(format) } } @@ -710,12 +710,12 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error) case "email", "hostname", "ipv4", "ipv6", "uri", "uri-reference": default: // Try to check for custom defined formats - if _, ok := SchemaStringFormats[format]; !ok && validationOpts.SchemaFormatValidationEnabled { + if _, ok := SchemaStringFormats[format]; !ok && validationOpts.schemaFormatValidationEnabled { return unsupportedFormat(format) } } } - if schema.Pattern != "" && !validationOpts.SchemaPatternValidationDisabled { + if schema.Pattern != "" && !validationOpts.schemaPatternValidationDisabled { if err = schema.compilePattern(); err != nil { return err } @@ -771,13 +771,13 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) (err error) } } - if v := schema.Default; v != nil { + if v := schema.Default; v != nil && !validationOpts.schemaDefaultsValidationDisabled { if err := schema.VisitJSON(v); err != nil { return fmt.Errorf("invalid default: %w", err) } } - if x := schema.Example; x != nil && !validationOpts.ExamplesValidationDisabled { + if x := schema.Example; x != nil && !validationOpts.examplesValidationDisabled { if err := validateExampleValue(ctx, x, schema); err != nil { return fmt.Errorf("invalid example: %w", err) } diff --git a/openapi3/validation_options.go b/openapi3/validation_options.go index a74364dae..343b6836e 100644 --- a/openapi3/validation_options.go +++ b/openapi3/validation_options.go @@ -7,10 +7,11 @@ type ValidationOption func(options *ValidationOptions) // ValidationOptions provides configuration for validating OpenAPI documents. type ValidationOptions struct { - SchemaFormatValidationEnabled bool - SchemaPatternValidationDisabled bool - ExamplesValidationDisabled bool examplesValidationAsReq, examplesValidationAsRes bool + examplesValidationDisabled bool + schemaDefaultsValidationDisabled bool + schemaFormatValidationEnabled bool + schemaPatternValidationDisabled bool } type validationOptionsKey struct{} @@ -19,7 +20,7 @@ type validationOptionsKey struct{} // By default, schema format validation is disabled. func EnableSchemaFormatValidation() ValidationOption { return func(options *ValidationOptions) { - options.SchemaFormatValidationEnabled = true + options.schemaFormatValidationEnabled = true } } @@ -27,7 +28,7 @@ func EnableSchemaFormatValidation() ValidationOption { // By default, schema format validation is disabled. func DisableSchemaFormatValidation() ValidationOption { return func(options *ValidationOptions) { - options.SchemaFormatValidationEnabled = false + options.schemaFormatValidationEnabled = false } } @@ -35,14 +36,30 @@ func DisableSchemaFormatValidation() ValidationOption { // By default, schema pattern validation is enabled. func EnableSchemaPatternValidation() ValidationOption { return func(options *ValidationOptions) { - options.SchemaPatternValidationDisabled = false + options.schemaPatternValidationDisabled = false } } // DisableSchemaPatternValidation makes Validate not return an error when validating patterns that are not supported by the Go regexp engine. func DisableSchemaPatternValidation() ValidationOption { return func(options *ValidationOptions) { - options.SchemaPatternValidationDisabled = true + options.schemaPatternValidationDisabled = true + } +} + +// EnableSchemaDefaultsValidation does the opposite of DisableSchemaDefaultsValidation. +// By default, schema default values are validated against their schema. +func EnableSchemaDefaultsValidation() ValidationOption { + return func(options *ValidationOptions) { + options.schemaDefaultsValidationDisabled = false + } +} + +// DisableSchemaDefaultsValidation disables schemas' default field validation. +// By default, schema default values are validated against their schema. +func DisableSchemaDefaultsValidation() ValidationOption { + return func(options *ValidationOptions) { + options.schemaDefaultsValidationDisabled = true } } @@ -50,7 +67,7 @@ func DisableSchemaPatternValidation() ValidationOption { // By default, all schema examples are validated. func EnableExamplesValidation() ValidationOption { return func(options *ValidationOptions) { - options.ExamplesValidationDisabled = false + options.examplesValidationDisabled = false } } @@ -58,7 +75,7 @@ func EnableExamplesValidation() ValidationOption { // By default, all schema examples are validated. func DisableExamplesValidation() ValidationOption { return func(options *ValidationOptions) { - options.ExamplesValidationDisabled = true + options.examplesValidationDisabled = true } }