├── fixtures ├── go-swagger │ ├── remotes │ │ ├── integer.json │ │ ├── folder │ │ │ └── folderInteger.json │ │ └── subSchemas.json │ ├── specs │ │ ├── deeper │ │ │ ├── stringProp.json │ │ │ └── arrayProp.json │ │ ├── resolution2.json │ │ ├── resolution.json │ │ └── response_name.json │ ├── templates │ │ └── swagger_json_embed.gotmpl │ ├── bugs │ │ ├── 155 │ │ │ └── swagger.yml │ │ ├── 162 │ │ │ └── swagger.yml │ │ ├── 163 │ │ │ └── swagger.yml │ │ ├── 193 │ │ │ ├── spec1.json │ │ │ └── spec2.json │ │ ├── 195 │ │ │ └── swagger.json │ │ ├── 196 │ │ │ └── swagger.yml │ │ ├── 217 │ │ │ ├── interface.yml │ │ │ ├── array.yml │ │ │ ├── map.yml │ │ │ └── string.yml │ │ ├── 248 │ │ │ └── swagger.json │ │ ├── 249 │ │ │ └── swagger.json │ │ ├── 251 │ │ │ └── swagger.yml │ │ ├── 252 │ │ │ └── swagger.json │ │ ├── 287 │ │ │ └── swagger.yml │ │ ├── 319 │ │ │ └── swagger.yml │ │ ├── 342 │ │ │ ├── fixture-342-2.yaml │ │ │ ├── fixture-342-3.yaml │ │ │ └── fixture-342.yaml │ │ ├── 436 │ │ │ └── swagger.yml │ │ ├── 453 │ │ │ └── swagger.yml │ │ ├── 454 │ │ │ └── swagger.yml │ │ ├── 455 │ │ │ └── swagger.yml │ │ ├── 465 │ │ │ └── swagger.yml │ │ ├── 500 │ │ │ └── swagger.yml │ │ ├── 511 │ │ │ └── swagger.yml │ │ ├── 524 │ │ │ └── swagger.yml │ │ ├── 628 │ │ │ └── swagger.yml │ │ ├── 740 │ │ │ └── swagger.yml │ │ ├── 743 │ │ │ └── swagger.yml │ │ ├── 763 │ │ │ └── swagger.yml │ │ ├── 774 │ │ │ └── swagger.yml │ │ ├── 776 │ │ │ ├── error.yaml │ │ │ ├── item.yaml │ │ │ ├── swagger-template.yml │ │ │ ├── spec.yaml │ │ │ └── param.yaml │ │ ├── 786 │ │ │ └── swagger.yml │ │ ├── 809 │ │ │ └── swagger.yml │ │ ├── 825 │ │ │ └── swagger.yml │ │ ├── 844 │ │ │ └── swagger.json │ │ ├── 846 │ │ │ └── swagger.yml │ │ ├── 881 │ │ │ ├── swagger.yml │ │ │ └── deep.yml │ │ ├── 890 │ │ │ ├── path │ │ │ │ └── health_check.yaml │ │ │ └── swagger.yaml │ │ ├── 899 │ │ │ └── swagger.yml │ │ ├── 981 │ │ │ └── swagger.json │ │ ├── 987 │ │ │ └── swagger.yml │ │ ├── 1010 │ │ │ └── swagger.yml │ │ ├── 1111 │ │ │ └── arrayParam.json │ │ ├── 1171 │ │ │ └── swagger.yaml │ │ ├── 1216 │ │ │ └── swagger.yml │ │ ├── 1238 │ │ │ └── swagger.yaml │ │ └── 1289 │ │ │ ├── fixture-1289-3.yaml │ │ │ ├── fixture-1289-4.yaml │ │ │ ├── fixture-1289-2.yaml │ │ │ └── fixture-1289.yaml │ ├── expansion │ │ ├── params.json │ │ ├── circularSpec.json │ │ ├── circularRefs.json │ │ ├── circularSpec.yaml │ │ └── invalid-refs.json │ └── petstores │ │ └── petstore.json ├── jsonschema_suite │ ├── remotes │ │ ├── integer.json │ │ ├── folder │ │ │ └── folderInteger.json │ │ ├── subSchemas.json │ │ └── name.json │ ├── optional │ │ ├── ecmascript-regex.json │ │ └── zeroTerminatedFloats.json │ ├── minItems.json │ ├── maxItems.json │ ├── definitions.json │ ├── pattern.json │ ├── minLength.json │ ├── maxLength.json │ ├── minProperties.json │ ├── maxProperties.json │ ├── maximum.json │ ├── minimum.json │ ├── default.json │ ├── required.json │ ├── multipleOf.json │ ├── anyOf.json │ ├── oneOf.json │ ├── refRemote.json │ └── enum.json ├── bugs │ ├── 6 │ │ ├── no-responses.json │ │ └── empty-responses.json │ ├── 18 │ │ ├── schema.json │ │ ├── parameters.json │ │ ├── headerItems.json │ │ ├── paramItems.json │ │ └── headers.json │ ├── 39 │ │ └── swagger.yml │ ├── 43 │ │ ├── fixture-43.yaml │ │ ├── fixture-43-fail.yaml │ │ ├── fixture-1456.yaml │ │ └── fixture-43-variants.yaml │ ├── 52 │ │ └── swagger.json │ ├── 53 │ │ └── noswagger.json │ ├── 61 │ │ ├── unresolved-ref-for-name.json │ │ └── multiple-refs.json │ ├── 62 │ │ └── swagger.json │ ├── 63 │ │ └── swagger.json │ ├── 73 │ │ ├── fixture-responses-3.yaml │ │ ├── fixture-responses-2.yaml │ │ ├── fixture-responses.yaml │ │ ├── fixture-swagger.yaml │ │ ├── fixture-swagger-3.yaml │ │ ├── fixture-swagger-good.yaml │ │ └── fixture-swagger-2.yaml │ ├── 102 │ │ └── fixture-102.json │ ├── 1341 │ │ ├── fixture-1341-good.yaml │ │ ├── fixture-1341-2.yaml │ │ ├── fixture-1341-4.yaml │ │ ├── fixture-1341.yaml │ │ ├── fixture-1341-3.yaml │ │ └── fixture-1341-5.yaml │ ├── 1429 │ │ ├── swagger.yaml │ │ ├── flatten-1429.yaml │ │ ├── responses.yaml │ │ └── expand-1429.yaml │ ├── 1621 │ │ ├── responses.yaml │ │ └── parameters.yaml │ ├── 2137 │ │ └── fixture-2137.yaml │ └── 123-validate │ │ └── fixture-123.json ├── local_expansion │ ├── item.yaml │ └── spec.yaml ├── recursive_expansion │ ├── item.yaml │ └── spec.yaml ├── validation │ ├── fixture-1289-good.yaml │ ├── fixture-1289-donotload.json │ ├── fixture-1289-donotload.yaml │ ├── fixture-empty-paths.json │ ├── invalid-referenced.yml │ ├── fixture-1289.yaml │ ├── fixture-invalid-example-property.yaml │ ├── fixture-valid-example-property.yaml │ ├── fixture-1050.yaml │ ├── fixture-bad-response.yaml │ ├── fixture-342-2.yaml │ ├── fixture-no-response.yaml │ ├── valid-referenced.yml │ ├── fixture-1243-2.yaml │ ├── fixture-1243.yaml │ ├── fixture-1243-3.yaml │ ├── fixture-1243-good.yaml │ ├── fixture-859-good.yaml │ ├── type-keyword-mismatch.yaml │ ├── fixture-581.yaml │ ├── fixture-859.yaml │ ├── fixture-859-2.yaml │ ├── fixture-1238.yaml │ ├── fixture-43-2.json │ ├── fixture-342.yaml │ ├── fixture-581-good-numbers.yaml │ ├── fixture-581-good.yaml │ ├── fixture-161-2.json │ ├── fixture-161.json │ └── fixture-161-good.json ├── schemas │ └── int-enum.json └── pruning │ └── schema.json ├── .gitignore ├── .gitattributes ├── options_test.go ├── .github ├── workflows │ ├── go-test.yml │ ├── auto-merge.yml │ ├── release.yml │ ├── contributors.yml │ ├── tag-release.yml │ ├── scanner.yml │ ├── codeql.yml │ └── bump-release.yml ├── DCO.md └── dependabot.yaml ├── update-fixtures.sh ├── .editorconfig ├── slice_validator_test.go ├── SECURITY.md ├── pools_debug_test.go ├── benchmark_test.go ├── debug.go ├── BENCHMARK.md ├── debug_test.go ├── go.mod ├── rexp.go ├── post ├── defaulter.go └── prune.go ├── .golangci.yml ├── context_test.go ├── pools_test.go ├── schema_option_test.go ├── context.go ├── formats_test.go ├── options.go ├── helpers_test.go └── formats.go /fixtures/go-swagger/remotes/integer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | secrets.yml 2 | coverage.out 3 | *.cov 4 | *.out 5 | playground 6 | -------------------------------------------------------------------------------- /fixtures/go-swagger/specs/deeper/stringProp.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "string" 3 | } -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/remotes/integer.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /fixtures/go-swagger/remotes/folder/folderInteger.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /fixtures/go-swagger/templates/swagger_json_embed.gotmpl: -------------------------------------------------------------------------------- 1 | ./swagger_json_embed.gotmpl 2 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/remotes/folder/folderInteger.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "integer" 3 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # gofmt always uses LF, whereas Git uses CRLF on Windows. 2 | *.go text eol=lf 3 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-responses-3.yaml: -------------------------------------------------------------------------------- 1 | definitions: 2 | NotFound: 3 | description: Not found 4 | -------------------------------------------------------------------------------- /fixtures/go-swagger/specs/deeper/arrayProp.json: -------------------------------------------------------------------------------- 1 | { 2 | "type":"array", 3 | "items": { 4 | "type": "string" 5 | } 6 | } -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/890/path/health_check.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | summary: Health Check 3 | responses: 4 | 200: 5 | description: Server OK -------------------------------------------------------------------------------- /fixtures/go-swagger/remotes/subSchemas.json: -------------------------------------------------------------------------------- 1 | { 2 | "integer": { 3 | "type": "integer" 4 | }, 5 | "refToInteger": { 6 | "$ref": "#/integer" 7 | } 8 | } -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/remotes/subSchemas.json: -------------------------------------------------------------------------------- 1 | { 2 | "integer": { 3 | "type": "integer" 4 | }, 5 | "refToInteger": { 6 | "$ref": "#/integer" 7 | } 8 | } -------------------------------------------------------------------------------- /fixtures/go-swagger/specs/resolution2.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "http://localhost:1234", 3 | "items": { 4 | "id": "deeper/", 5 | "items": { 6 | "$ref": "arrayProp.json#/items" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/825/swagger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 0.0.0 5 | title: Simple API 6 | paths: 7 | /: 8 | responses: 9 | 200: 10 | description: OK 11 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/776/error.yaml: -------------------------------------------------------------------------------- 1 | definitions: 2 | Error: 3 | type: object 4 | properties: 5 | code: 6 | type: integer 7 | format: int32 8 | message: 9 | type: string 10 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-responses-2.yaml: -------------------------------------------------------------------------------- 1 | definitions: 2 | fixture: 3 | type: string 4 | parameters: 5 | param1: 6 | name: queryParam1 7 | in: query 8 | type: string 9 | responses: 10 | NotFound: 11 | description: Not found 12 | -------------------------------------------------------------------------------- /fixtures/local_expansion/item.yaml: -------------------------------------------------------------------------------- 1 | type: object 2 | required: 3 | - title 4 | properties: 5 | id: 6 | type: integer 7 | format: uint64 8 | readOnly: true 9 | title: 10 | type: string 11 | minLength: 2 12 | maxLength: 80 13 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/776/item.yaml: -------------------------------------------------------------------------------- 1 | type: object 2 | required: 3 | - title 4 | properties: 5 | id: 6 | type: integer 7 | format: uint64 8 | readOnly: true 9 | title: 10 | type: string 11 | minLength: 2 12 | maxLength: 80 13 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/remotes/name.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "orNull": { 4 | "anyOf": [ 5 | {"type": "null"}, 6 | {"$ref": "#"} 7 | ] 8 | } 9 | }, 10 | "type": "string" 11 | } 12 | -------------------------------------------------------------------------------- /fixtures/go-swagger/specs/resolution.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "http://localhost:1234", 3 | "items": { 4 | "id": "deeper/", 5 | "items": { 6 | "$ref": "stringProp.json" 7 | } 8 | }, 9 | "definitions": { 10 | "bool": { 11 | "$ref": "boolProp.json" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /fixtures/bugs/62/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger of additionalProperties in pathItem" 6 | }, 7 | "paths": { 8 | "/": { 9 | "invalid-property": { 10 | "description": "blah" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /fixtures/bugs/1429/swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | summary: GET 10 | operationId: getAll 11 | responses: 12 | 200: 13 | description: Ok 14 | 400: 15 | $ref: './responses.yaml#/responses/BadRequest' -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-responses.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Responses 4 | version: 0.1.0 5 | responses: 6 | NotFound: 7 | description: Not found 8 | 9 | paths: 10 | /: 11 | get: 12 | summary: GET 13 | operationId: getAll 14 | responses: 15 | '200': 16 | description: Ok 17 | -------------------------------------------------------------------------------- /fixtures/bugs/6/no-responses.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid no responses" 6 | }, 7 | "paths": { 8 | "/foo": { 9 | "get": { 10 | "description": "foo" 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /fixtures/recursive_expansion/item.yaml: -------------------------------------------------------------------------------- 1 | item: 2 | type: object 3 | required: 4 | - title 5 | properties: 6 | id: 7 | type: integer 8 | format: uint64 9 | readOnly: true 10 | title: 11 | type: string 12 | minLength: 2 13 | maxLength: 80 14 | subitem: 15 | $ref: "item.yaml#/item" 16 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/890/swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Some API 4 | description: Some API 5 | version: "1.0.0" 6 | 7 | host: someapi.com 8 | 9 | schemes: 10 | - https 11 | 12 | basePath: /v1/ 13 | 14 | produces: 15 | - application/json 16 | paths: 17 | /health_check: 18 | $ref: ./path/health_check.yaml 19 | -------------------------------------------------------------------------------- /options_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "testing" 8 | ) 9 | 10 | // This test must be synchronized to avoid issues with -race 11 | // TODO(TEST) 12 | func TestOptions_SetContinueOnErrors(_ *testing.T) { 13 | } 14 | -------------------------------------------------------------------------------- /fixtures/bugs/52/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger" : "2.0", 3 | "info" : { 4 | "version" : "1.0", 5 | "title" : "Hello World", 6 | "description" : "Simple Hello World API, with Get operation to one resource path, no request parameters defined" 7 | }, 8 | "host" : "api.tibco.com", 9 | "basePath" : "/v1", 10 | "schemes" : [ "http" ] 11 | } 12 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | summary: GET 10 | operationId: getAll 11 | responses: 12 | '200': 13 | description: Ok 14 | '404': 15 | $ref: './fixture-responses.yaml#/responses/NotFound' 16 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/899/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: api 4 | version: 1.0.0 5 | consumes: 6 | - application/json 7 | produces: 8 | - application/json 9 | schemes: 10 | - http 11 | basePath: / 12 | paths: 13 | /trailingslashpath/: 14 | get: 15 | responses: 16 | 204: 17 | description: OK no content 18 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-swagger-3.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | summary: GET 10 | operationId: getAll 11 | responses: 12 | '200': 13 | description: Ok 14 | '404': 15 | $ref: 'fixture-responses-3.yaml#/definitions/NotFound' 16 | -------------------------------------------------------------------------------- /.github/workflows/go-test.yml: -------------------------------------------------------------------------------- 1 | name: go test 2 | 3 | permissions: 4 | pull-requests: read 5 | contents: read 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | 12 | pull_request: 13 | 14 | jobs: 15 | test: 16 | uses: go-openapi/ci-workflows/.github/workflows/go-test.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 17 | secrets: inherit 18 | -------------------------------------------------------------------------------- /fixtures/bugs/6/empty-responses.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid no responses" 6 | }, 7 | "paths": { 8 | "/foo": { 9 | "get": { 10 | "description": "foo", 11 | "responses": {} 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /fixtures/bugs/1429/flatten-1429.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | paths: 6 | /: 7 | get: 8 | summary: GET 9 | operationId: getAll 10 | responses: 11 | "200": 12 | description: Ok 13 | "400": 14 | description: Bad request 15 | schema: 16 | $ref: '#/definitions/Error' 17 | -------------------------------------------------------------------------------- /fixtures/bugs/53/noswagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : "1.0", 4 | "title" : "Hello World", 5 | "description" : "Simple Hello World API, with Get operation to one resource path, no request parameters defined" 6 | }, 7 | "host" : "api.tibco.com", 8 | "basePath" : "/v1", 9 | "schemes" : [ "http" ], 10 | "paths": { 11 | "/": { 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | pull_request: 8 | 9 | jobs: 10 | dependabot: 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | uses: go-openapi/ci-workflows/.github/workflows/auto-merge.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 15 | secrets: inherit 16 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-swagger-good.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | responses: 7 | NotFound: 8 | description: Not found 9 | 10 | paths: 11 | /: 12 | get: 13 | summary: GET 14 | operationId: getAll 15 | responses: 16 | '200': 17 | description: Ok 18 | '404': 19 | $ref: '#/responses/NotFound' 20 | -------------------------------------------------------------------------------- /fixtures/bugs/2137/fixture-2137.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | description: Test 4 | title: Test 5 | version: "0.0.1" 6 | basePath: /v1 7 | consumes: 8 | - application/json 9 | produces: 10 | - application/json 11 | 12 | paths: 13 | /test/a: 14 | $ref: "#/paths/~1test" 15 | /test: 16 | get: 17 | operationId: test 18 | responses: 19 | 200: 20 | description: OK 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - v[0-9]+* 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | release: 13 | permissions: 14 | contents: write 15 | uses: go-openapi/ci-workflows/.github/workflows/release.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 16 | with: 17 | tag: ${{ github.ref_name }} 18 | secrets: inherit 19 | -------------------------------------------------------------------------------- /fixtures/bugs/1621/responses.yaml: -------------------------------------------------------------------------------- 1 | responses: 2 | 3 | V4Generic401Response: 4 | description: Permission denied 5 | schema: 6 | $ref: "./definitions.yaml#/definitions/V4GenericResponse" 7 | examples: 8 | application/json: 9 | { 10 | "code": "PERMISSION_DENIED", 11 | "message": "The requested resource cannot be accessed using the provided authentication details." 12 | } 13 | 14 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/optional/ecmascript-regex.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "ECMA 262 regex non-compliance", 4 | "schema": { "format": "regex" }, 5 | "tests": [ 6 | { 7 | "description": "ECMA 262 has no support for \\Z anchor from .NET", 8 | "data": "^\\S(|(.|\\n)*\\S)\\Z", 9 | "valid": false 10 | } 11 | ] 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /.github/workflows/contributors.yml: -------------------------------------------------------------------------------- 1 | name: Contributors 2 | 3 | on: 4 | schedule: 5 | - cron: '18 4 * * 6' 6 | 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | contributors: 14 | permissions: 15 | pull-requests: write 16 | contents: write 17 | uses: go-openapi/ci-workflows/.github/workflows/contributors.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 18 | secrets: inherit 19 | -------------------------------------------------------------------------------- /.github/workflows/tag-release.yml: -------------------------------------------------------------------------------- 1 | name: Release on tag 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | push: 8 | tags: 9 | - v[0-9]+* 10 | 11 | jobs: 12 | gh-release: 13 | name: Create release 14 | permissions: 15 | contents: write 16 | uses: go-openapi/ci-workflows/.github/workflows/release.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 17 | with: 18 | tag: ${{ github.ref_name }} 19 | secrets: inherit 20 | -------------------------------------------------------------------------------- /update-fixtures.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu -o pipefail 4 | dir=$(git rev-parse --show-toplevel) 5 | scratch=$(mktemp -d -t tmp.XXXXXXXXXX) 6 | 7 | function finish { 8 | rm -rf "$scratch" 9 | } 10 | trap finish EXIT SIGHUP SIGINT SIGTERM 11 | 12 | cd "$scratch" 13 | git clone https://github.com/json-schema-org/JSON-Schema-Test-Suite Suite 14 | cp -r Suite/tests/draft4/* "$dir/fixtures/jsonschema_suite" 15 | cp -a Suite/remotes "$dir/fixtures/jsonschema_suite" 16 | -------------------------------------------------------------------------------- /fixtures/bugs/43/fixture-43.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | responses: 10 | '200': 11 | description: Ok 12 | schema: 13 | type: object 14 | properties: 15 | a: 16 | type: string 17 | items: 18 | type: string 19 | default: "xyz" 20 | example: "123" 21 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/465/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'Test' 5 | schemes: 6 | - http 7 | basePath: /v1/fancyAPI 8 | produces: 9 | - application/json 10 | consumes: 11 | - application/json 12 | paths: 13 | /key/{id}: 14 | delete: 15 | parameters: 16 | - name: id 17 | in: path 18 | type: integer 19 | required: true 20 | responses: 21 | '200': 22 | description: OK 23 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1289-good.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: 'fixture 1289' 5 | version: '1.0' 6 | produces: 7 | - application/json 8 | paths: 9 | '/fixture': 10 | get: 11 | operationId: op1 12 | responses: 13 | '200': 14 | description: 'erroneous response' 15 | schema: 16 | # Expect clean 17 | $ref: '#/definitions/someIds' 18 | 19 | definitions: 20 | someIds: 21 | type: string 22 | -------------------------------------------------------------------------------- /.github/workflows/scanner.yml: -------------------------------------------------------------------------------- 1 | name: Vulnerability scans 2 | 3 | on: 4 | branch_protection_rule: 5 | push: 6 | branches: [ "master" ] 7 | schedule: 8 | - cron: '18 4 * * 3' 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | scanners: 15 | permissions: 16 | contents: read 17 | security-events: write 18 | uses: go-openapi/ci-workflows/.github/workflows/scanner.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # V0.1.1 19 | secrets: inherit 20 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/217/interface.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'string-body-api' 5 | paths: 6 | /echo: 7 | post: 8 | operationId: "postEcho" 9 | summary: Post an object 10 | parameters: 11 | - name: body 12 | in: body 13 | description: this argument is a string 14 | schema: 15 | type: object 16 | 17 | responses: 18 | '200': 19 | description: All is good 20 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/optional/zeroTerminatedFloats.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "some languages do not distinguish between different types of numeric value", 4 | "schema": { 5 | "type": "integer" 6 | }, 7 | "tests": [ 8 | { 9 | "description": "a float is not an integer even without fractional part", 10 | "data": 1.0, 11 | "valid": false 12 | } 13 | ] 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/776/swagger-template.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Test 4 | version: '1.0.0' 5 | host: localhost 6 | basePath: / 7 | produces: 8 | - application/json 9 | schemes: 10 | - http 11 | paths: 12 | /healthy: 13 | get: 14 | operationId: getHealthy 15 | responses: 16 | default: 17 | description: Unexpected error 18 | schema: 19 | $ref: '#/definitions/Error' 20 | definitions: 21 | Error: 22 | $ref: ./error.yaml#/definitions/Error 23 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1010/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | paths: 3 | /widgets/: 4 | get: 5 | summary: Retrieve all widgets. 6 | parameters: 7 | - name: category_id 8 | in: query 9 | description: Return the widgets that are associated with this category. 10 | required: true 11 | type: array 12 | collectionFormat: "multi" 13 | items: 14 | type: string 15 | pattern: '^[0-9abcdefghjkmnpqrtuvwxyz]{29}$' 16 | definitions: {} 17 | -------------------------------------------------------------------------------- /fixtures/go-swagger/expansion/params.json: -------------------------------------------------------------------------------- 1 | { 2 | "parameters": { 3 | "id": { 4 | "type": "integer", 5 | "format": "int64", 6 | "in": "path", 7 | "required": true 8 | }, 9 | "tag": { 10 | "type": "string", 11 | "in": "query", 12 | "required": false 13 | }, 14 | "query": { 15 | "$ref": "#/parameters/tag" 16 | } 17 | }, 18 | "paths": { 19 | "/cars/{id}": { 20 | "parameters": [ 21 | { "$ref": "#/parameters/id"} 22 | ] 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /fixtures/validation/fixture-1289-donotload.json: -------------------------------------------------------------------------------- 1 | "someIds": { 2 | "type": "array", 3 | "example": [ 4 | 413, 5 | 231, 6 | 777 7 | ], 8 | "default": [ 9 | 413, 10 | 231, 11 | 777 12 | ], 13 | "items": { 14 | "type": "number" 15 | } 16 | }, 17 | "getSomeIds": { 18 | "type": "object", 19 | "properties": { 20 | "someIds": { 21 | "$ref": "#/definitions/someIds", 22 | "type": "array" 23 | } 24 | } 25 | }, 26 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1289-donotload.yaml: -------------------------------------------------------------------------------- 1 | "someIds": { 2 | "type": "array", 3 | "example": [ 4 | 413, 5 | 231, 6 | 777 7 | ], 8 | "default": [ 9 | 413, 10 | 231, 11 | 777 12 | ], 13 | "items": { 14 | "type": "number" 15 | } 16 | }, 17 | "getSomeIds": { 18 | "type": "object", 19 | "properties": { 20 | "someIds": { 21 | "$ref": "#/definitions/someIds", 22 | "type": "array" 23 | } 24 | } 25 | }, 26 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/217/array.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'array-body-api' 5 | paths: 6 | /echo: 7 | post: 8 | operationId: "postEcho" 9 | summary: Post an object 10 | parameters: 11 | - name: body 12 | in: body 13 | description: this argument is a string array 14 | schema: 15 | type: array 16 | items: 17 | type: string 18 | responses: 19 | '200': 20 | description: All is good 21 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/881/swagger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 0.0.0 5 | title: Breaking API as described by emsa23 6 | paths: 7 | /: 8 | get: 9 | operationId: getFoo 10 | responses: 11 | 200: 12 | $ref: '#/responses/200' 13 | responses: 14 | '200': 15 | description: ok 16 | headers: 17 | status: 18 | type: array 19 | items: 20 | type: string 21 | enum: 22 | - NEW 23 | - PUBLISHED 24 | - OPEN 25 | - FINISHED 26 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/217/map.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'string-body-api' 5 | paths: 6 | /echo: 7 | post: 8 | operationId: "postEcho" 9 | summary: Post an object 10 | parameters: 11 | - name: body 12 | in: body 13 | description: this argument is a string 14 | schema: 15 | type: object 16 | additionalProperties: 17 | type: integer 18 | format: int64 19 | responses: 20 | '200': 21 | description: All is good 22 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/217/string.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'string-body-api' 5 | paths: 6 | /echo: 7 | post: 8 | operationId: "postEcho" 9 | summary: Post a string, get the same string back. 10 | parameters: 11 | - name: body 12 | in: body 13 | description: this argument is a string 14 | schema: 15 | type: string 16 | responses: 17 | '200': 18 | description: this return value is a string 19 | schema: 20 | type: string 21 | 22 | -------------------------------------------------------------------------------- /fixtures/bugs/73/fixture-swagger-2.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | summary: GET 10 | operationId: getAll 11 | parameters: 12 | - $ref: 'fixture-responses-2.yaml#/parameters/param1' 13 | - name: param2 14 | in: body 15 | schema: 16 | $ref: 'fixture-responses-2.yaml#/definitions/fixture' 17 | responses: 18 | '200': 19 | description: Ok 20 | '404': 21 | $ref: 'fixture-responses-2.yaml#/responses/NotFound' 22 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-empty-paths.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "", 5 | "version": "1.0.0", 6 | "title": "issue#161", 7 | "termsOfService": "http://helloreverb.com/terms/", 8 | "contact": { 9 | "name": "apiteam@wordnik.com" 10 | }, 11 | "license": { 12 | "name": "Apache 2.0", 13 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 14 | } 15 | }, 16 | "host": "petstore.swagger.wordnik.com", 17 | "basePath": "/v2", 18 | "schemes": [ 19 | "http" 20 | ], 21 | "paths": {} 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "master" ] 6 | pull_request: 7 | branches: [ "master" ] 8 | paths-ignore: # remove this clause if CodeQL is a required check 9 | - '**/*.md' 10 | schedule: 11 | - cron: '39 19 * * 5' 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | codeql: 18 | permissions: 19 | contents: read 20 | security-events: write 21 | uses: go-openapi/ci-workflows/.github/workflows/codeql.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 22 | secrets: inherit 23 | -------------------------------------------------------------------------------- /fixtures/bugs/18/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid pattern in schema" 6 | }, 7 | "paths": { 8 | "/foo": { 9 | "get": { 10 | "produces": [ 11 | "text/plain" 12 | ], 13 | "responses": { 14 | "200": { 15 | "description": "Successful", 16 | "schema": { 17 | "type": "string", 18 | "pattern": ")<-- bad pattern" 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /fixtures/validation/invalid-referenced.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "0.1.0" 5 | title: referenced validation invalid 6 | paths: 7 | /: 8 | get: 9 | responses: 10 | default: 11 | description: the record 12 | 13 | parameters: 14 | rateLimit: 15 | name: X-Rate-Limit 16 | in: header 17 | type: integer 18 | format: int32 19 | 20 | responses: 21 | notFound: 22 | description: Not found 23 | 24 | definitions: 25 | record: 26 | type: object 27 | properties: 28 | createdAt: 29 | type: string 30 | format: date-time 31 | 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/342/fixture-342-2.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-342 4 | version: 0.0.1 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /get_main_object: 17 | get: 18 | tags: 19 | - maindata 20 | parameters: 21 | $ref: "#/parameters/sid" 22 | responses: 23 | '200': 24 | 25 | parameters: 26 | sid: 27 | in: query 28 | required: true 29 | type: integer 30 | format: int64 31 | 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/342/fixture-342-3.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-342 4 | version: 0.0.1 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /get_main_object: 17 | get: 18 | tags: 19 | - maindata 20 | parameters: 21 | - $ref: "#/parameters/sid" 22 | responses: 23 | '200': 24 | 25 | parameters: 26 | sid: 27 | name: sid 28 | in: query 29 | required: true 30 | type: integer 31 | format: int64 32 | 33 | -------------------------------------------------------------------------------- /fixtures/local_expansion/spec.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: Item API 5 | description: Item API 6 | version: "1.0.0" 7 | host: item.api.local 8 | basePath: /v1 9 | securityDefinitions: 10 | key: 11 | type: apiKey 12 | name: x-item-token 13 | in: header 14 | security: 15 | - key: [] 16 | consumes: 17 | - application/json 18 | produces: 19 | - application/json 20 | schemes: 21 | - http 22 | paths: 23 | /item: 24 | get: 25 | operationId: GetItem 26 | responses: 27 | 200: 28 | description: item detail response 29 | schema: 30 | "$ref": "item.yaml" 31 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/776/spec.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: Item API 5 | description: Item API 6 | version: "1.0.0" 7 | host: item.api.local 8 | basePath: /v1 9 | securityDefinitions: 10 | key: 11 | type: apiKey 12 | name: x-item-token 13 | in: header 14 | security: 15 | - key: [] 16 | consumes: 17 | - application/json 18 | produces: 19 | - application/json 20 | schemes: 21 | - http 22 | paths: 23 | /item: 24 | get: 25 | operationId: GetItem 26 | responses: 27 | 200: 28 | description: item detail response 29 | schema: 30 | $ref: "item.yaml" 31 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 2 10 | trim_trailing_whitespace = true 11 | 12 | # Set default charset 13 | [*.{js,py,go,scala,rb,java,html,css,less,sass,md}] 14 | charset = utf-8 15 | 16 | # Tab indentation (no size specified) 17 | [*.go] 18 | indent_style = tab 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | # Matches the exact files either package.json or .travis.yml 24 | [{package.json,.travis.yml}] 25 | indent_style = space 26 | indent_size = 2 27 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/524/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | 3 | definitions: 4 | m1: 5 | type: object 6 | required: ['f1'] 7 | properties: 8 | f1: 9 | type: string 10 | minLength: 1 11 | maxLength: 2 12 | f2: 13 | type: array 14 | minItems: 1 15 | maxItems: 10 16 | items: 17 | $ref: "#/definitions/m2" 18 | m2: 19 | type: object 20 | required: ['k1'] 21 | properties: 22 | k1: 23 | type: string 24 | minLength: 1 25 | maxLength: 2 26 | 27 | info: 28 | description: test 29 | title: test 30 | version: 1.1.0 31 | paths: {} 32 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1289.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: 'fixture 1289' 5 | version: '1.0' 6 | produces: 7 | - application/json 8 | paths: 9 | '/fixture': 10 | get: 11 | operationId: op1 12 | responses: 13 | '200': 14 | description: 'erroneous response' 15 | schema: 16 | $ref: '#/definitions/getSomeIds' 17 | 18 | definitions: 19 | getSomeIds: 20 | type: object 21 | properties: 22 | # Expect a clear message about $ref siblings 23 | someIds: 24 | $ref: '#/definitions/someIds' 25 | type: array 26 | 27 | someIds: 28 | type: string 29 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/881/deep.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 0.0.0 5 | title: Breaking API as described by emsa23 6 | paths: 7 | /: 8 | get: 9 | operationId: getFoo 10 | responses: 11 | 200: 12 | $ref: '#/responses/200' 13 | responses: 14 | '200': 15 | description: ok 16 | headers: 17 | status: 18 | type: array 19 | items: 20 | type: array 21 | items: 22 | type: array 23 | items: 24 | type: string 25 | enum: 26 | - NEW 27 | - PUBLISHED 28 | - OPEN 29 | - FINISHED 30 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-invalid-example-property.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1231 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /servers/getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | schema: 23 | type: object 24 | properties: 25 | id: 26 | type: number 27 | example: ABC 28 | responses: 29 | '200': 30 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-valid-example-property.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1231 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /servers/getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | schema: 23 | type: object 24 | properties: 25 | id: 26 | type: number 27 | example: 123 28 | responses: 29 | '200': 30 | -------------------------------------------------------------------------------- /fixtures/bugs/43/fixture-43-fail.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | "/": 8 | get: 9 | operationId: getBody 10 | parameters: 11 | - name: yet_other_server_id 12 | in: body 13 | schema: 14 | # Invalid array definition 15 | type: array 16 | properties: 17 | other: 18 | type: string 19 | responses: 20 | '200': 21 | description: ko 22 | # Invalid array definition 23 | schema: 24 | type: array 25 | properties: 26 | another: 27 | type: string 28 | -------------------------------------------------------------------------------- /fixtures/bugs/18/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid pattern in parameter" 6 | }, 7 | "parameters": { 8 | "userId": { 9 | "name": "userId", 10 | "in": "path", 11 | "type": "string", 12 | "pattern": ")<-- bad pattern", 13 | "required": true 14 | } 15 | }, 16 | "paths": { 17 | "/users/{userId}": { 18 | "parameters": [ 19 | { "$ref": "#/parameters/userId" } 20 | ], 21 | "get": { 22 | "responses": { 23 | "200": { 24 | "description": "Successful" 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /slice_validator_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/go-openapi/testify/v2/assert" 10 | ) 11 | 12 | // Test edge cases in slice_validator which are difficult 13 | // to simulate with specs 14 | // (this one is a trivial, just to check all methods are filled) 15 | func TestSliceValidator_EdgeCases(t *testing.T) { 16 | s := newSliceValidator("", "", nil, nil, false, nil, nil, nil, nil, nil) 17 | s.SetPath("path") 18 | assert.Equal(t, "path", s.Path) 19 | 20 | r := s.Validate(nil) 21 | assert.NotNil(t, r) 22 | assert.True(t, r.IsValid()) 23 | } 24 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/763/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Test 4 | description: Test Service 5 | version: '1.0.0' 6 | host: localhost 7 | basePath: / 8 | produces: 9 | - application/json 10 | schemes: 11 | - http 12 | paths: 13 | /myMethod: 14 | get: 15 | operationId: get_test 16 | summary: Get a list of int32s. 17 | responses: 18 | 200: 19 | schema: 20 | $ref: '#/definitions/test_list' 21 | definitions: 22 | test_list: 23 | type: object 24 | properties: 25 | the_array: 26 | type: array 27 | items: 28 | minimum: 0 29 | maximum: 10 30 | type: integer 31 | format: int32 32 | -------------------------------------------------------------------------------- /fixtures/bugs/18/headerItems.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid pattern in headers" 6 | }, 7 | "paths": { 8 | "/foo": { 9 | "get": { 10 | "responses": { 11 | "default": { 12 | "headers": { 13 | "X-Foo": { 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "pattern": ")<-- bad pattern" 18 | } 19 | } 20 | }, 21 | "description": "Generic Error" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/342/fixture-342.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-342 4 | version: 0.0.1 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /get_main_object: 17 | get: 18 | tags: 19 | - maindata 20 | parameters: 21 | - name: sid 22 | in: body 23 | required: true 24 | $ref: "#/definitions/sample_info/properties/sid" 25 | responses: 26 | '200': 27 | 28 | definitions: 29 | sample_info: 30 | type: object 31 | properties: 32 | sid: 33 | type: string 34 | 35 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1289/fixture-1289-3.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1289 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | required: true 23 | schema: 24 | type: object 25 | properties: 26 | someIds: 27 | type: array 28 | items: 29 | type: number 30 | responses: 31 | '200': 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/776/param.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: Item API 5 | description: Item API 6 | version: "1.0.0" 7 | host: item.api.local 8 | basePath: /v1 9 | securityDefinitions: 10 | key: 11 | type: apiKey 12 | name: x-item-token 13 | in: header 14 | security: 15 | - key: [] 16 | consumes: 17 | - application/json 18 | produces: 19 | - application/json 20 | schemes: 21 | - http 22 | paths: 23 | /item: 24 | get: 25 | operationId: GetItem 26 | parameters: 27 | - name: body 28 | in: body 29 | required: true 30 | schema: 31 | $ref: "item.yaml" 32 | responses: 33 | 204: 34 | description: item detail response 35 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/251/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'Test' 5 | schemes: 6 | - http 7 | produces: 8 | - application/json 9 | consumes: 10 | - application/json 11 | paths: 12 | /key/{id}: 13 | delete: 14 | parameters: 15 | - name: id 16 | in: path 17 | type: integer 18 | required: true 19 | responses: 20 | '200': 21 | description: OK 22 | definitions: 23 | example: 24 | type: object 25 | required: 26 | - begin 27 | properties: 28 | begin: 29 | type: string 30 | format: date-time 31 | end: 32 | type: string 33 | format: date-time 34 | name: 35 | type: string 36 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/287/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'Test' 5 | schemes: 6 | - http 7 | produces: 8 | - application/json 9 | - "text/plain" 10 | consumes: 11 | - application/json 12 | paths: 13 | /key/{id}: 14 | delete: 15 | parameters: 16 | - name: id 17 | in: path 18 | type: integer 19 | required: true 20 | responses: 21 | '200': 22 | description: OK 23 | definitions: 24 | example: 25 | type: object 26 | required: 27 | - begin 28 | properties: 29 | begin: 30 | type: string 31 | format: date-time 32 | end: 33 | type: string 34 | format: date-time 35 | name: 36 | type: string 37 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1050.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | description: >- 4 | Minimal swagger file to demonstrate a dot-in-th-path problem 5 | version: 0.0.1 6 | title: test 7 | tags: 8 | - name: test 9 | description: test the go-swagger generator bug 10 | paths: 11 | /{fileName}.{fileExt}: 12 | get: 13 | tags: 14 | - test 15 | operationId: test 16 | parameters: 17 | - name: fileName 18 | in: path 19 | required: true 20 | type: string 21 | - name: fileExt 22 | in: path 23 | required: true 24 | type: string 25 | responses: 26 | '204': 27 | description: successful operation 28 | '500': 29 | description: Operation error -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1289/fixture-1289-4.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1289 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | required: true 23 | schema: 24 | type: object 25 | properties: 26 | someIds: 27 | $ref: '#/definitions/idList' 28 | responses: 29 | '200': 30 | definitions: 31 | idList: 32 | type: array 33 | items: 34 | type: number 35 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-bad-response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: checking $ref siblings in response 5 | version: '1.0' 6 | description: | 7 | This one checks that wrong response declaraion with $ref sibling 8 | is correcly handled and reported 9 | 10 | produces: 11 | - application/json 12 | paths: 13 | /fixture: 14 | get: 15 | operationId: op1 16 | parameters: 17 | - name: myid 18 | in: body 19 | schema: 20 | $ref: '#/definitions/myId' 21 | responses: 22 | 200: 23 | description: 'response with $ref sibling' 24 | schema: 25 | $ref: '#/definitions/someIds' 26 | 27 | definitions: 28 | myId: 29 | type: string 30 | someIds: 31 | type: integer 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/809/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | 3 | info: 4 | version: "1.0.0" 5 | title: Private to-do list 6 | description: | 7 | A very simple api description that makes a json only API to submit to do's. 8 | 9 | produces: 10 | - application/json 11 | 12 | consumes: 13 | - application/json 14 | 15 | paths: 16 | /foo: 17 | get: 18 | parameters: 19 | - name: "groups[]" 20 | in: query 21 | type: array 22 | collectionFormat: multi 23 | items: 24 | type: string 25 | 26 | definitions: 27 | genericResource: 28 | description: generic resource 29 | properties: 30 | meta: 31 | type: string 32 | required: 33 | - meta 34 | additionalProperties: 35 | type: object 36 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-342-2.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-342 4 | description: A variant on issue-342 with an incorrect attempt to fix the $ref sibling issue 5 | version: 0.0.1 6 | license: 7 | name: MIT 8 | host: localhost:8081 9 | basePath: /api/v1 10 | schemes: 11 | - http 12 | consumes: 13 | - application/json 14 | produces: 15 | - application/json 16 | paths: 17 | /get_main_object: 18 | get: 19 | tags: 20 | - maindata 21 | parameters: 22 | # Here, declared as a property and not an item: cannot marshall 23 | $ref: "#/parameters/sid" 24 | responses: 25 | '200': 26 | 27 | parameters: 28 | sid: 29 | #name: mysid 30 | in: body 31 | required: true 32 | type: integer 33 | format: int64 34 | 35 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/248/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "paths": { 3 | "/thing": { 4 | "post": { 5 | "summary": "SomePost", 6 | "description": "", 7 | "parameters": [{ 8 | "name": "optional_query_enum", 9 | "enum": [ 10 | "OPTIONAL_ONE", 11 | "OPTIONAL_TWO" 12 | ], 13 | "required": false, 14 | "type": "string", 15 | "in": "query" 16 | }], 17 | "operationId": "CreateThing" 18 | } 19 | } 20 | }, 21 | "host": "connect.squareup.com", 22 | "schemes": ["https"], 23 | "produces": ["application/json"], 24 | "swagger": "2.0", 25 | "definitions": {}, 26 | "consumes": ["application/json"], 27 | "info": { 28 | "title": "Test API", 29 | "version": "1.23" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/786/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Test API 4 | description: my test 5 | version: "0.1.0" 6 | 7 | host: test.test.com 8 | 9 | schemes: 10 | - https 11 | 12 | basePath: / 13 | 14 | produces: 15 | - application/json 16 | consumes: 17 | - application/json 18 | 19 | paths: 20 | /: 21 | get: 22 | summary: Find a thing 23 | description: It's acool thing 24 | tags: 25 | - Root 26 | responses: 27 | 307: 28 | description: Redirect to a thing. 29 | 30 | definitions: 31 | MyFirstObject: 32 | type: object 33 | properties: 34 | entree_choice: 35 | type: object 36 | additionalProperties: 37 | type: string 38 | enum: 39 | - Beef 40 | - Vegan 41 | -------------------------------------------------------------------------------- /fixtures/go-swagger/specs/response_name.json: -------------------------------------------------------------------------------- 1 | { 2 | "consumes": [ 3 | "application/json", 4 | "application/x-www-form-urlencoded" 5 | ], 6 | "paths": { 7 | "/testing": { 8 | "put": { 9 | "operationId": "putTesting", 10 | "responses": { 11 | "200": { 12 | "description": "Success message", 13 | "x-go-name": "AlternateName" 14 | } 15 | } 16 | } 17 | } 18 | }, 19 | "produces": [ 20 | "application/json", 21 | "application/json; charset=utf-8" 22 | ], 23 | "swagger": "2.0", 24 | "info": { 25 | "title": "test formats for form params", 26 | "version": "0.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-no-response.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: "Load Balancing Service API" 5 | description: API for the Load Balancing Service 6 | version: "20170115" 7 | 8 | basePath: /20170115 9 | 10 | paths: 11 | /loadBalancers/{loadBalancerId}/backendSets: 12 | get: 13 | summary: "ListBackendSets" 14 | tags: ['loadBalancer'] 15 | description: Lists all backend sets associated with a given load balancer. 16 | operationId: "ListBackendSets" 17 | # fixed that: Missing parameter in path 18 | parameters: 19 | - name: loadBalancerId 20 | in: path 21 | type: string 22 | # fixed that: should be required 23 | required: true 24 | produces: 25 | - "application/json" 26 | responses: 27 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1289/fixture-1289-2.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1289 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /servers/getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | required: true 23 | schema: 24 | type: object 25 | properties: 26 | someIds: 27 | $ref: '#/definitions/someIds' 28 | type: array 29 | responses: 30 | '200': 31 | definitions: 32 | someIds: 33 | type: array 34 | items: 35 | type: number 36 | -------------------------------------------------------------------------------- /fixtures/recursive_expansion/spec.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: Item API 5 | description: Item API 6 | version: "1.0.0" 7 | host: item.api.local 8 | basePath: /v1 9 | securityDefinitions: 10 | key: 11 | type: apiKey 12 | name: x-item-token 13 | in: header 14 | security: 15 | - key: [] 16 | consumes: 17 | - application/json 18 | produces: 19 | - application/json 20 | schemes: 21 | - http 22 | responses: 23 | itemResponse: 24 | description: Item 25 | schema: 26 | $ref: "item.yaml#/item" 27 | paths: 28 | /item: 29 | get: 30 | operationId: GetItem 31 | responses: 32 | 200: 33 | description: item detail response 34 | schema: 35 | $ref: "item.yaml#/item" 36 | default: 37 | $ref: "#/responses/itemResponse" 38 | 39 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/196/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Validation Issue 4 | description: Endpoints 5 | version: 0.0.1 6 | basePath: /v1 7 | consumes: 8 | - application/json 9 | produces: 10 | - application/json 11 | 12 | paths: 13 | /events: 14 | post: 15 | operationId: postEvents 16 | parameters: 17 | - name: event 18 | in: body 19 | description: Event to post 20 | required: true 21 | schema: 22 | $ref: '#/definitions/Event' 23 | responses: 24 | '201': 25 | $ref: '#/responses/CreatedEventResponse' 26 | 27 | definitions: 28 | Event: 29 | type: string 30 | 31 | responses: 32 | CreatedEventResponse: 33 | description: Successfully created an event 34 | schema: 35 | $ref: '#/definitions/Event' 36 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/249/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "consumes": [ 3 | "application/json", 4 | "application/x-www-form-urlencoded" 5 | ], 6 | "paths": { 7 | "/testing": { 8 | "put": { 9 | "operationId": "putTesting", 10 | "parameters": [{ 11 | "in": "body", 12 | "name": "testingThis", 13 | "schema": { 14 | "items": { 15 | "format": "int64", 16 | "type": "integer" 17 | }, 18 | "type": "array" 19 | } 20 | }], 21 | "responses": { 22 | "200": { 23 | "description": "Success message" 24 | } 25 | } 26 | } 27 | } 28 | }, 29 | "produces": [ 30 | "application/json", 31 | "application/json; charset=utf-8" 32 | ], 33 | "swagger": "2.0" 34 | } 35 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/minItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minItems validation", 4 | "schema": {"minItems": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": [1, 2], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": [], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /fixtures/bugs/18/paramItems.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid pattern in items" 6 | }, 7 | "parameters": { 8 | "fooBody": { 9 | "name": "user", 10 | "in": "body", 11 | "description": "user to add to the system", 12 | "required": true, 13 | "schema": { 14 | "type": "array", 15 | "items": { 16 | "type": "string", 17 | "pattern": ")<-- bad pattern" 18 | } 19 | } 20 | } 21 | }, 22 | "paths": { 23 | "/foo": { 24 | "parameters": [ 25 | { "$ref": "#/parameters/fooBody" } 26 | ], 27 | "get": { 28 | "responses": { 29 | "200": { 30 | "description": "Successful" 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/maxItems.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxItems validation", 4 | "schema": {"maxItems": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": [1], 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": [1, 2], 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": [1, 2, 3], 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-arrays", 23 | "data": "foobar", 24 | "valid": true 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/846/swagger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 0.0.0 5 | title: Test846 API 6 | description: a simple API to test issue 846 7 | paths: 8 | /: 9 | get: 10 | operationId: getFoo 11 | responses: 12 | 200: 13 | description: OK 14 | schema: 15 | type: object 16 | properties: 17 | Foo: 18 | type: integer 19 | format: int64 20 | 404: 21 | description: NotFound 22 | schema: 23 | type: object 24 | properties: 25 | Message: 26 | type: string 27 | 500: 28 | description: Error 29 | schema: 30 | type: object 31 | properties: 32 | Message: 33 | type: string 34 | -------------------------------------------------------------------------------- /fixtures/validation/valid-referenced.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "0.1.0" 5 | title: referenced validation 6 | paths: 7 | /: 8 | get: 9 | parameters: 10 | - $ref: "#/parameters/rateLimit" 11 | responses: 12 | default: 13 | description: the record 14 | schema: 15 | $ref: "#/definitions/record" 16 | 404: 17 | $ref: "#/responses/notFound" 18 | 19 | parameters: 20 | rateLimit: 21 | name: X-Rate-Limit 22 | in: header 23 | type: integer 24 | format: int32 25 | 26 | responses: 27 | notFound: 28 | description: Not found 29 | schema: 30 | $ref: "#/definitions/record" 31 | 32 | definitions: 33 | record: 34 | type: object 35 | properties: 36 | createdAt: 37 | type: string 38 | format: date-time 39 | 40 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | This policy outlines the commitment and practices of the go-openapi maintainers regarding security. 4 | 5 | ## Supported Versions 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 0.22.x | :white_check_mark: | 10 | 11 | ## Reporting a vulnerability 12 | 13 | If you become aware of a security vulnerability that affects the current repository, 14 | please report it privately to the maintainers. 15 | 16 | Please follow the instructions provided by github to 17 | [Privately report a security vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). 18 | 19 | TL;DR: on Github, navigate to the project's "Security" tab then click on "Report a vulnerability". 20 | -------------------------------------------------------------------------------- /fixtures/bugs/18/headers.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger invalid pattern in headers" 6 | }, 7 | "paths": { 8 | "/foo": { 9 | "get": { 10 | "responses": { 11 | "default": { 12 | "headers": { 13 | "X-Foo": { 14 | "type": "string", 15 | "pattern": ")<-- bad pattern" 16 | } 17 | }, 18 | "description": "Generic Error" 19 | }, 20 | "402": { 21 | "headers": { 22 | "X-Foo": { 23 | "type": "string", 24 | "pattern": ")<-- bad pattern" 25 | } 26 | }, 27 | "description": "Generic Error" 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/454/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | 3 | info: 4 | version: "1.0.0" 5 | title: Private to-do list 6 | description: | 7 | A very simple api description that makes a json only API to submit to do's. 8 | 9 | produces: 10 | - application/json 11 | 12 | consumes: 13 | - application/json 14 | 15 | paths: 16 | /models: 17 | get: 18 | operationId: modelOp 19 | summary: many model variations 20 | description: Used to see if a codegen can render all the possible parameter variations for a header param 21 | tags: 22 | - testcgen 23 | responses: 24 | default: 25 | description: Generic Out 26 | 27 | definitions: 28 | genericResource: 29 | description: generic resource 30 | properties: 31 | meta: 32 | type: string 33 | required: 34 | - meta 35 | additionalProperties: 36 | type: object 37 | -------------------------------------------------------------------------------- /pools_debug_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //go:build validatedebug 5 | 6 | package validate 7 | 8 | import ( 9 | "path/filepath" 10 | "testing" 11 | 12 | "github.com/go-openapi/loads" 13 | "github.com/go-openapi/strfmt" 14 | "github.com/go-openapi/testify/v2/require" 15 | ) 16 | 17 | func Test_Debug_2866(t *testing.T) { 18 | // This test to be run with build flag "validatedebug": it uses the debug pools and asserts that 19 | // all allocated objects are indeed redeemed at the end of the spec validation. 20 | 21 | resetPools() 22 | fp := filepath.Join("fixtures", "bugs", "2866", "2866.yaml") 23 | 24 | doc, err := loads.Spec(fp) 25 | require.NoError(t, err) 26 | require.NotNil(t, doc) 27 | 28 | require.NoError(t, Spec(doc, strfmt.Default)) 29 | 30 | require.True(t, pools.allIsRedeemed(t)) 31 | } 32 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/981/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "paths": {}, 4 | "definitions": { 5 | "User": { 6 | "description": "User - user model", 7 | "type": "object", 8 | "properties": { 9 | "first_name": { 10 | "type": "string", 11 | "x-go-name": "FirstName" 12 | }, 13 | "id": { 14 | "type": "string", 15 | "x-go-name": "ID" 16 | }, 17 | "last_name": { 18 | "type": "string", 19 | "x-go-name": "LastName" 20 | }, 21 | "user_type": { 22 | "description": "User type", 23 | "type": "integer", 24 | "format": "int64", 25 | "maximum": 5, 26 | "minimum": 1, 27 | "x-go-name": "Type" 28 | } 29 | }, 30 | "x-go-package": "github.com/go-swagger/go-swagger/fixtures/bugs/981" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1243-2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: "Load Balancing Service API" 5 | description: API for the Load Balancing Service 6 | version: "20170115" 7 | 8 | basePath: /20170115 9 | 10 | paths: 11 | /loadBalancers/{loadBalancerId}/backendSets: 12 | get: 13 | summary: "ListBackendSets" 14 | tags: ['loadBalancer'] 15 | description: Lists all backend sets associated with a given load balancer. 16 | operationId: "ListBackendSets" 17 | # Missing parameter in path 18 | produces: 19 | - "application/json" 20 | responses: 21 | 200: 22 | description: The list is being retrieved. 23 | # fixed that: $ref is forbidden in headers 24 | headers: 25 | opc-response-id: 26 | description: | 27 | Unique identifier for the response. 28 | type: string 29 | -------------------------------------------------------------------------------- /fixtures/bugs/39/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | version: "1.0.0" 4 | title: "fragment-param test" 5 | schemes: 6 | - http 7 | basePath: /service 8 | paths: 9 | /foo/bar{fragment}.{subfragment}: 10 | get: 11 | description: "lookup foo with bar*.*, where * is some string" 12 | parameters: 13 | - name: "fragment" 14 | in: "path" 15 | type: string 16 | required: true 17 | description: "this fragment header parameter is not recognized by codegen" 18 | - name: "subfragment" 19 | in: "path" 20 | type: string 21 | required: true 22 | description: "this subfragment header parameter is not recognized by codegen" 23 | produces: 24 | - text/plain 25 | responses: 26 | '200': 27 | description: "Successful" 28 | schema: 29 | type: string 30 | '400': 31 | description: "Bad request" 32 | 33 | -------------------------------------------------------------------------------- /fixtures/schemas/int-enum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "schema": { 4 | "type": "object", 5 | "properties": { 6 | "sizes": { 7 | "type": "object", 8 | "properties": { 9 | "first": { 10 | "type": "object", 11 | "properties": { 12 | "count": { 13 | "type": "integer", 14 | "default": 3, 15 | "enum": [3, 5, 7] 16 | } 17 | }, 18 | "required": ["count"] 19 | } 20 | }, 21 | "required": ["first"] 22 | } 23 | }, 24 | "required": ["sizes"] 25 | }, 26 | "valid": { 27 | "sizes": { 28 | "first": { 29 | "count": 3 30 | } 31 | } 32 | }, 33 | "invalid": { 34 | "sizes": { 35 | "first": { 36 | "count": 2 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1289/fixture-1289.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-1289 4 | version: '1.0' 5 | license: 6 | name: MIT 7 | host: localhost:8081 8 | basePath: /api/v1 9 | schemes: 10 | - http 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /servers/getSomeIds: 17 | get: 18 | operationId: getSomeIdsOps 19 | parameters: 20 | - name: getSomeIds 21 | in: body 22 | required: true 23 | schema: 24 | type: object 25 | properties: 26 | someIds: 27 | $ref: '#/definitions/someIds' 28 | type: array 29 | responses: 30 | '200': 31 | definitions: 32 | someIds: 33 | type: array 34 | example: 35 | - 413, 36 | - 231, 37 | - 777 38 | default: 39 | - 413, 40 | - 231, 41 | - 777 42 | items: 43 | type: number 44 | -------------------------------------------------------------------------------- /benchmark_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/go-openapi/loads" 11 | "github.com/go-openapi/strfmt" 12 | "github.com/go-openapi/testify/v2/require" 13 | ) 14 | 15 | func Benchmark_KubernetesSpec(b *testing.B) { 16 | fp := filepath.Join("fixtures", "go-swagger", "canary", "kubernetes", "swagger.json") 17 | doc, err := loads.Spec(fp) 18 | require.NoError(b, err) 19 | require.NotNil(b, doc) 20 | 21 | b.Run("validating kubernetes API", func(b *testing.B) { 22 | b.ResetTimer() 23 | b.ReportAllocs() 24 | 25 | for b.Loop() { 26 | validator := NewSpecValidator(doc.Schema(), strfmt.Default) 27 | validator.Options.SkipSchemataResult = true 28 | res, _ := validator.Validate(doc) 29 | if res == nil || !res.IsValid() { 30 | b.FailNow() 31 | } 32 | } 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/844/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "anyOf bug", 5 | "version": "0.0.1", 6 | "description": "repro", 7 | "license": { 8 | "name": "Apache 2.0", 9 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 10 | } 11 | }, 12 | "definitions": { 13 | "foo": { 14 | "type": "object" 15 | }, 16 | "bar": { 17 | "type": "object" 18 | } 19 | }, 20 | "paths": { 21 | "/": { 22 | "get": { 23 | "responses": { 24 | "200": { 25 | "description": "OK", 26 | "schema": { 27 | "allOf": [ 28 | { 29 | "$ref": "#/definitions/foo" 30 | }, 31 | { 32 | "$ref": "#/definitions/bar" 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/987/swagger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 1.0.0 5 | title: Greeting Server 6 | 7 | basePath: "/api/greeting/2.0" 8 | 9 | paths: 10 | /revisit: 11 | post: 12 | produces: 13 | - application/json 14 | consumes: 15 | - application/json 16 | parameters: 17 | - name: site 18 | required: true 19 | type: string 20 | in: query 21 | description: site name 22 | 23 | - name: userlist 24 | in: body 25 | description: list of users 26 | required: true 27 | schema: 28 | "$ref": "#/definitions/Userlist" 29 | 30 | 31 | operationId: trackingRevisit 32 | 33 | responses: 34 | 200: 35 | description: return list of users which need revisit 36 | schema: 37 | type: string 38 | 39 | definitions: 40 | Userlist: 41 | type: array 42 | items: 43 | type: object 44 | -------------------------------------------------------------------------------- /debug.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "fmt" 8 | "log" 9 | "os" 10 | "path/filepath" 11 | "runtime" 12 | ) 13 | 14 | var ( 15 | // Debug is true when the SWAGGER_DEBUG env var is not empty. 16 | // It enables a more verbose logging of validators. 17 | Debug = os.Getenv("SWAGGER_DEBUG") != "" 18 | // validateLogger is a debug logger for this package 19 | validateLogger *log.Logger 20 | ) 21 | 22 | func init() { 23 | debugOptions() 24 | } 25 | 26 | func debugOptions() { 27 | validateLogger = log.New(os.Stdout, "validate:", log.LstdFlags) 28 | } 29 | 30 | func debugLog(msg string, args ...any) { 31 | // A private, trivial trace logger, based on go-openapi/spec/expander.go:debugLog() 32 | if Debug { 33 | _, file1, pos1, _ := runtime.Caller(1) 34 | validateLogger.Printf("%s:%d: %s", filepath.Base(file1), pos1, fmt.Sprintf(msg, args...)) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/195/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "consumes": [ 3 | "application/json", 4 | "application/x-www-form-urlencoded" 5 | ], 6 | "paths": { 7 | "/testing": { 8 | "get": { 9 | "operationId": "getTesting", 10 | "parameters": [ 11 | { 12 | "allowEmptyValue": false, 13 | "in": "query", 14 | "name": "testingThis", 15 | "required": false, 16 | "type": "integer" 17 | } 18 | ], 19 | "responses": { 20 | "200": { 21 | "description": "Success message" 22 | } 23 | } 24 | } 25 | } 26 | }, 27 | "produces": [ 28 | "application/json", 29 | "application/json; charset=utf-8" 30 | ], 31 | "swagger": "2.0" 32 | } 33 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/500/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: Test 5 | description: "Test" 6 | termsOfService: 'test.com/' 7 | host: api.test.com 8 | basePath: /v1 9 | schemes: 10 | - https 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | paths: 16 | /payment/{invoice_id}/payments/{payment_id}: 17 | get: 18 | description: Get payment info 19 | tags: 20 | - Invoices 21 | - Payments 22 | - Drama 23 | - Failure 24 | - HotMess 25 | operationId: getPaymentByID 26 | parameters: 27 | - name: invoice_id 28 | in: path 29 | description: Invoice ID 30 | required: true 31 | type: string 32 | - name: payment_id 33 | in: path 34 | description: Payment ID 35 | required: true 36 | type: string 37 | responses: 38 | '200': 39 | description: Simple response 40 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/774/swagger.yml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | version: 0.0.0 5 | title: Breaking API as described by christianklotz 6 | paths: 7 | /stores: 8 | get: 9 | operationId: getFoo 10 | responses: 11 | 200: 12 | schema: 13 | type: array 14 | items: 15 | $ref: '#/definitions/Foo' 16 | definitions: 17 | Foo: 18 | type: object 19 | properties: 20 | hasOmitEmptyTrue: 21 | type: array 22 | x-omitempty: true 23 | items: 24 | type: string 25 | enum: 26 | - some 27 | - values 28 | hasOmitEmptyFalse: 29 | type: array 30 | x-omitempty: false 31 | items: 32 | type: string 33 | enum: 34 | - some 35 | - values 36 | noOmitEmpty: 37 | type: array 38 | items: 39 | type: string 40 | enum: 41 | - some 42 | - values 43 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1216/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 0.0.0 4 | title: 'Test' 5 | definitions: 6 | Test.Pet_Dog: 7 | allOf: 8 | - $ref: '#/definitions/Test.Pet' 9 | - required: 10 | - name 11 | - barks 12 | type: object 13 | properties: 14 | name: 15 | type: string 16 | barks: 17 | type: boolean 18 | type: object 19 | Test.Pet_Cat: 20 | allOf: 21 | - $ref: '#/definitions/Test.Pet' 22 | - required: 23 | - name 24 | - evil 25 | type: object 26 | properties: 27 | name: 28 | type: string 29 | evil: 30 | type: boolean 31 | type: object 32 | Test.Pet: 33 | required: 34 | - discriminator 35 | discriminator: discriminator 36 | type: object 37 | properties: 38 | discriminator: 39 | type: string 40 | paths: 41 | /: 42 | get: 43 | responses: 44 | 200: 45 | description: Dummy path 46 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/455/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'Test' 5 | schemes: 6 | - http 7 | basePath: /v1/fancyAPI 8 | produces: 9 | - application/json 10 | consumes: 11 | - application/json 12 | 13 | definitions: 14 | in_object: 15 | type: object 16 | required: [test_id1, test_id2] 17 | properties: 18 | test_id1: 19 | type: integer 20 | test_id2: 21 | type: integer 22 | 23 | out_obj: 24 | type: object 25 | required: [fld1, fld2] 26 | properties: 27 | fld1: 28 | type: integer 29 | minimum: 0 30 | maximim: 100 31 | fld2: 32 | $ref: "#/definitions/in_object" 33 | fld3: 34 | $ref: "#/definitions/in_object" 35 | 36 | paths: 37 | '/key/{id}': 38 | delete: 39 | parameters: 40 | - name: id 41 | in: path 42 | type: integer 43 | required: true 44 | responses: 45 | '200': 46 | description: OK 47 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/definitions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "valid definition", 4 | "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 5 | "tests": [ 6 | { 7 | "description": "valid definition schema", 8 | "data": { 9 | "definitions": { 10 | "foo": {"type": "integer"} 11 | } 12 | }, 13 | "valid": true 14 | } 15 | ] 16 | }, 17 | { 18 | "description": "invalid definition", 19 | "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, 20 | "tests": [ 21 | { 22 | "description": "invalid definition schema", 23 | "data": { 24 | "definitions": { 25 | "foo": {"type": 1} 26 | } 27 | }, 28 | "valid": false 29 | } 30 | ] 31 | } 32 | ] 33 | -------------------------------------------------------------------------------- /fixtures/bugs/63/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger global parameters" 6 | }, 7 | "parameters": { 8 | "userId": { 9 | "name": "userId", 10 | "in": "path", 11 | "type": "string", 12 | "required": true 13 | } 14 | }, 15 | "paths": { 16 | "/foo": { 17 | "get": { 18 | "responses": { 19 | "200": { 20 | "description": "Successful" 21 | } 22 | } 23 | } 24 | }, 25 | "/bar": { 26 | "get": { 27 | "responses": { 28 | "200": { 29 | "description": "Successful" 30 | } 31 | } 32 | } 33 | }, 34 | "/users/{userId}": { 35 | "parameters": [ 36 | { "$ref": "#/parameters/userId" } 37 | ], 38 | "get": { 39 | "responses": { 40 | "200": { 41 | "description": "Successful" 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/319/swagger.yml: -------------------------------------------------------------------------------- 1 | info: 2 | description: a spec for issue 319 on github 3 | title: bug 319 4 | version: 1.0.0 5 | paths: {} 6 | consumes: 7 | - application/json 8 | produces: 9 | - application/json 10 | schemes: 11 | - http 12 | swagger: "2.0" 13 | definitions: 14 | Base: 15 | description: Base class 16 | discriminator: dType 17 | properties: 18 | dType: 19 | type: string 20 | description: discriminating type 21 | required: 22 | - dType 23 | 24 | Derived: 25 | description: Derived class 26 | allOf: 27 | - "$ref": "#/definitions/Base" 28 | - required: 29 | - name 30 | properties: 31 | name: 32 | type: string 33 | description: name of the property 34 | 35 | Container: 36 | description: Container type 37 | properties: 38 | mapNoWorky: 39 | type: object 40 | additionalProperties: 41 | $ref: "#/definitions/Base" 42 | required: 43 | - mapNoWorky 44 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/pattern.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "pattern validation", 4 | "schema": {"pattern": "^a*$"}, 5 | "tests": [ 6 | { 7 | "description": "a matching pattern is valid", 8 | "data": "aaa", 9 | "valid": true 10 | }, 11 | { 12 | "description": "a non-matching pattern is invalid", 13 | "data": "abc", 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-strings", 18 | "data": true, 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "pattern is not anchored", 25 | "schema": {"pattern": "a+"}, 26 | "tests": [ 27 | { 28 | "description": "matches a substring", 29 | "data": "xxaayy", 30 | "valid": true 31 | } 32 | ] 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /fixtures/bugs/61/unresolved-ref-for-name.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger global parameters" 6 | }, 7 | "parameters": { 8 | "userId": { 9 | "name": "userId", 10 | "in": "path", 11 | "type": "string", 12 | "required": true 13 | } 14 | }, 15 | "paths": { 16 | "/foo": { 17 | "get": { 18 | "responses": { 19 | "200": { 20 | "description": "Successful" 21 | } 22 | } 23 | } 24 | }, 25 | "/bar": { 26 | "get": { 27 | "responses": { 28 | "200": { 29 | "description": "Successful" 30 | } 31 | } 32 | } 33 | }, 34 | "/users/{userId}": { 35 | "parameters": [{ 36 | "$ref": "#/parameters/userId" 37 | }], 38 | "get": { 39 | "responses": { 40 | "200": { 41 | "description": "Successful" 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/193/spec1.json: -------------------------------------------------------------------------------- 1 | { 2 | "consumes": [ 3 | "application/json", 4 | "application/x-www-form-urlencoded" 5 | ], 6 | "paths": { 7 | "/testing": { 8 | "put": { 9 | "operationId": "putTesting", 10 | "parameters": [ 11 | { 12 | "format": "date", 13 | "in": "formData", 14 | "name": "testingThis", 15 | "type": "string" 16 | } 17 | ], 18 | "responses": { 19 | "200": { 20 | "description": "Success message" 21 | } 22 | } 23 | } 24 | } 25 | }, 26 | "produces": [ 27 | "application/json", 28 | "application/json; charset=utf-8" 29 | ], 30 | "swagger": "2.0", 31 | "info": { 32 | "title": "test formats for form params", 33 | "version": "0.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/minLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minLength validation", 4 | "schema": {"minLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": "foo", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": "f", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 1, 24 | "valid": true 25 | }, 26 | { 27 | "description": "one supplementary Unicode code point is not long enough", 28 | "data": "\uD83D\uDCA9", 29 | "valid": false 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1243.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: "Load Balancing Service API" 5 | description: API for the Load Balancing Service 6 | version: "20170115" 7 | 8 | basePath: /20170115 9 | 10 | paths: 11 | /loadBalancers/{loadBalancerId}/backendSets: 12 | get: 13 | summary: "ListBackendSets" 14 | tags: ['loadBalancer'] 15 | description: Lists all backend sets associated with a given load balancer. 16 | operationId: "ListBackendSets" 17 | # error no param defined 18 | produces: 19 | - "application/json" 20 | responses: 21 | 200: 22 | # we should not have a forbidden property message here: instead 23 | description: The list is being retrieved. 24 | # $ref is forbidden in headers 25 | headers: 26 | opc-response-id: 27 | $ref: '#/x-descriptions/opc-response-id' 28 | 29 | x-descriptions: 30 | opc-response-id: 31 | description: | 32 | Unique identifier for the response. 33 | type: string 34 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/193/spec2.json: -------------------------------------------------------------------------------- 1 | { 2 | "consumes": [ 3 | "application/json", 4 | "application/x-www-form-urlencoded" 5 | ], 6 | "paths": { 7 | "/testing": { 8 | "put": { 9 | "operationId": "putTesting", 10 | "parameters": [ 11 | { 12 | "in": "formData", 13 | "items": { 14 | "format": "date", 15 | "type": "string" 16 | }, 17 | "name": "testingThis", 18 | "type": "array" 19 | } 20 | ], 21 | "responses": { 22 | "200": { 23 | "description": "Success message" 24 | } 25 | } 26 | } 27 | } 28 | }, 29 | "produces": [ 30 | "application/json", 31 | "application/json; charset=utf-8" 32 | ], 33 | "swagger": "2.0" 34 | } 35 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/maxLength.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxLength validation", 4 | "schema": {"maxLength": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": "f", 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": "fo", 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": "foo", 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-strings", 23 | "data": 100, 24 | "valid": true 25 | }, 26 | { 27 | "description": "two supplementary Unicode code points is long enough", 28 | "data": "\uD83D\uDCA9\uD83D\uDCA9", 29 | "valid": true 30 | } 31 | ] 32 | } 33 | ] 34 | -------------------------------------------------------------------------------- /fixtures/go-swagger/expansion/circularSpec.json: -------------------------------------------------------------------------------- 1 | {"swagger":"2.0","info":{"title":"Swagger Sample","description":"Sample API Playground.","version":"1.0.0"},"basePath":"/v1","schemes":["http"],"consumes":["application/vdn.sample.v1+json"],"produces":["application/vdn.sample.v1+json"],"paths":{"/books":{"get":{"summary":"List all books","operationId":"listBooks","tags":["books"],"responses":{"200":{"headers":{"Link":{"type":"string"}},"description":"An array of books","schema":{"type":"array","items":{"$ref":"#/definitions/Book"}}},"default":{"description":"generic error response","schema":{"$ref":"#/definitions/Error"}}}}}},"definitions":{"Book":{"type":"object","required":["title","summary"],"properties":{"title":{"type":"string","example":"Winnie the Pooh"},"summary":{"type":"string","example":"Famous children's book"},"related_books":{"type":"array","items":{"$ref":"#/definitions/Book"}}}},"Error":{"type":"object","readOnly":true,"properties":{"code":{"type":"integer","format":"int64","example":400},"message":{"type":"string","example":"Unexpected error"}},"required":["message"]}}} 2 | -------------------------------------------------------------------------------- /BENCHMARK.md: -------------------------------------------------------------------------------- 1 | # Benchmark 2 | 3 | Validating the Kubernetes Swagger API 4 | 5 | ## v0.22.6: 60,000,000 allocs 6 | ``` 7 | goos: linux 8 | goarch: amd64 9 | pkg: github.com/go-openapi/validate 10 | cpu: AMD Ryzen 7 5800X 8-Core Processor 11 | Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 8549863982 ns/op 7067424936 B/op 59583275 allocs/op 12 | ``` 13 | 14 | ## After refact PR: minor but noticable improvements: 25,000,000 allocs 15 | ``` 16 | go test -bench Spec 17 | goos: linux 18 | goarch: amd64 19 | pkg: github.com/go-openapi/validate 20 | cpu: AMD Ryzen 7 5800X 8-Core Processor 21 | Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 4064535557 ns/op 3379715592 B/op 25320330 allocs/op 22 | ``` 23 | 24 | ## After reduce GC pressure PR: 17,000,000 allocs 25 | ``` 26 | goos: linux 27 | goarch: amd64 28 | pkg: github.com/go-openapi/validate 29 | cpu: AMD Ryzen 7 5800X 8-Core Processor 30 | Benchmark_KubernetesSpec/validating_kubernetes_API-16 1 3758414145 ns/op 2593881496 B/op 17111373 allocs/op 31 | ``` 32 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1243-3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: "Load Balancing Service API" 5 | description: API for the Load Balancing Service 6 | version: "20170115" 7 | 8 | basePath: /20170115 9 | 10 | paths: 11 | /loadBalancers/{loadBalancerId}/backendSets: 12 | get: 13 | summary: "ListBackendSets" 14 | tags: ['loadBalancer'] 15 | description: Lists all backend sets associated with a given load balancer. 16 | operationId: "ListBackendSets" 17 | # fixed that: Missing parameter in path 18 | parameters: 19 | - name: loadBalancerId 20 | in: path 21 | type: string 22 | # Ah: should be required 23 | produces: 24 | - "application/json" 25 | responses: 26 | 200: 27 | description: The list is being retrieved. 28 | # fix that: $ref is forbidden in headers 29 | headers: 30 | opc-response-id: 31 | description: | 32 | Unique identifier for the response. 33 | type: string 34 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/743/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | 3 | info: 4 | title: Discriminator 5 | description: Discriminator bug example 6 | version: 0.0.1 7 | 8 | schemes: 9 | - http 10 | 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | 16 | definitions: 17 | 18 | Id: 19 | type: object 20 | discriminator: type 21 | required: 22 | - type 23 | - id 24 | properties: 25 | type: 26 | type: string 27 | id: 28 | type: integer 29 | 30 | Foo: 31 | type: object 32 | allOf: 33 | - $ref: "#/definitions/Id" 34 | 35 | Bar: 36 | type: object 37 | properties: 38 | bar: 39 | type: string 40 | 41 | Awol: 42 | type: object 43 | allOf: 44 | - $ref: "#/definitions/Foo" 45 | - $ref: "#/definitions/Bar" 46 | 47 | paths: 48 | 49 | /awol: 50 | get: 51 | operationId: awol 52 | summary: get awol 53 | responses: 54 | 200: 55 | description: awol 56 | schema: 57 | $ref: "#/definitions/Awol" 58 | -------------------------------------------------------------------------------- /fixtures/bugs/1429/responses.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Responses 4 | version: 0.1.0 5 | definitions: 6 | Error: 7 | type: object 8 | description: | 9 | Contains all the properties any error response from the API will contain. 10 | Some properties are optional so might be empty most of the time 11 | required: 12 | - code 13 | - message 14 | properties: 15 | code: 16 | description: the error code, this is not necessarily the http status code 17 | type: integer 18 | format: int32 19 | message: 20 | description: a human readable version of the error 21 | type: string 22 | helpUrl: 23 | description: an optional url for getting more help about this error 24 | type: string 25 | format: uri 26 | 27 | responses: 28 | BadRequest: 29 | description: Bad request 30 | schema: 31 | $ref: '#/definitions/Error' 32 | 33 | paths: 34 | /: 35 | get: 36 | summary: GET 37 | operationId: getAll 38 | responses: 39 | 200: 40 | description: Ok -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/155/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: '2.0' 4 | title: Test API 5 | 6 | basePath: /api/2.0/ 7 | schemes: 8 | - https 9 | consumes: 10 | - application/json 11 | produces: 12 | - application/json 13 | paths: 14 | '/sample/action/do-something': 15 | post: 16 | operationId: sampleDoSomethingAction 17 | parameters: 18 | - name: json body 19 | in: body 20 | required: true 21 | schema: 22 | $ref: "#/definitions/Actions_DoSomethingRequest" 23 | 24 | responses: 25 | '200': 26 | description: Success 27 | schema: 28 | $ref: '#/definitions/Actions_DoSomethingResponse' 29 | '401': 30 | description: Unauthorized 31 | '404': 32 | description: Not Found 33 | 34 | definitions: 35 | Actions_DoSomethingRequest: 36 | type: object 37 | properties: 38 | client_id: 39 | type: string 40 | 41 | Actions_DoSomethingResponse: 42 | type: object 43 | properties: 44 | result: 45 | type: string 46 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1243-good.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: "Load Balancing Service API" 5 | description: API for the Load Balancing Service 6 | version: "20170115" 7 | 8 | basePath: /20170115 9 | 10 | paths: 11 | /loadBalancers/{loadBalancerId}/backendSets: 12 | get: 13 | summary: "ListBackendSets" 14 | tags: ['loadBalancer'] 15 | description: Lists all backend sets associated with a given load balancer. 16 | operationId: "ListBackendSets" 17 | # fixed that: Missing parameter in path 18 | parameters: 19 | - name: loadBalancerId 20 | in: path 21 | type: string 22 | # fixed that: should be required 23 | required: true 24 | produces: 25 | - "application/json" 26 | responses: 27 | 200: 28 | description: The list is being retrieved. 29 | # fixed that: $ref is forbidden in headers 30 | headers: 31 | opc-response-id: 32 | description: | 33 | Unique identifier for the response. 34 | type: string 35 | -------------------------------------------------------------------------------- /fixtures/bugs/43/fixture-1456.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: fixture 4 | description: reproduce fixture go-swagger/go-swagger#1456 5 | version: "1.0.0" 6 | paths: 7 | /v1/collection: 8 | post: 9 | summary: Collection 10 | tags: 11 | - Collection 12 | parameters: 13 | - name: collection 14 | in: body 15 | required: true 16 | schema: 17 | $ref: '#/definitions/collection' 18 | responses: 19 | 200: 20 | description: success 21 | schema: 22 | type: string 23 | definitions: 24 | collection: 25 | type: object 26 | required: 27 | - id 28 | - title 29 | - items 30 | properties: 31 | id: 32 | type: string 33 | description: The unique ID 34 | title: 35 | type: string 36 | description: Title 37 | minLength: 1 38 | maxLength: 50 39 | items: 40 | type: array 41 | description: Items 42 | items: 43 | type: string 44 | example: 45 | id: item1 46 | title: Home 47 | items: 48 | - item2 49 | - item3 50 | -------------------------------------------------------------------------------- /fixtures/bugs/1429/expand-1429.yaml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | paths: 6 | /: 7 | get: 8 | summary: GET 9 | operationId: getAll 10 | responses: 11 | "200": 12 | description: Ok 13 | "400": 14 | description: Bad request 15 | schema: 16 | description: | 17 | Contains all the properties any error response from the API will contain. 18 | Some properties are optional so might be empty most of the time 19 | type: object 20 | required: 21 | - code 22 | - message 23 | properties: 24 | code: 25 | description: the error code, this is not necessarily the http status 26 | code 27 | type: integer 28 | format: int32 29 | helpUrl: 30 | description: an optional url for getting more help about this error 31 | type: string 32 | format: uri 33 | message: 34 | description: a human readable version of the error 35 | type: string 36 | -------------------------------------------------------------------------------- /fixtures/bugs/123-validate/fixture-123.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "TestSwagger", 5 | "version": "1.0", 6 | "title": "Test" 7 | }, 8 | "host": "127.0.0.1:8443", 9 | "basePath": "/", 10 | "schemes": [ 11 | "https" 12 | ], 13 | "paths": { 14 | "/api/v1/getx": { 15 | "post": { 16 | "operationId": "getx", 17 | "consumes": [ 18 | "application/json" 19 | ], 20 | "produces": [ 21 | "application/json" 22 | ], 23 | "responses": { 24 | "200": { 25 | "description": "Operation successful", 26 | "schema": { 27 | "$ref": "#/definitions/MyObj" 28 | } 29 | } 30 | }, 31 | "security": [] 32 | } 33 | } 34 | }, 35 | "definitions": { 36 | "MyObj": { 37 | "type": "object", 38 | "properties": { 39 | "name": { 40 | "type": "string" 41 | }, 42 | "child-objects": { 43 | "type": "array", 44 | "items": { 45 | "$ref": "#/definitions/MyObj" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/436/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | 3 | info: 4 | title: Discriminator 5 | description: Discriminator bug example 6 | version: 0.0.1 7 | 8 | schemes: 9 | - http 10 | 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | 16 | paths: 17 | /image: 18 | get: 19 | operationId: image 20 | summary: get image 21 | responses: 22 | 200: 23 | description: image 24 | schema: 25 | $ref: "#/definitions/Image" 26 | 27 | definitions: 28 | Links: 29 | type: array 30 | items: 31 | type: string 32 | Image: 33 | description: An image of an application and revision 34 | allOf: 35 | - $ref: '#/definitions/Links' 36 | type: object 37 | properties: 38 | created: 39 | description: The timestamp the image was created 40 | type: string 41 | format: date-time 42 | size: 43 | description: The size of the image, in bytes 44 | type: integer 45 | imageId: 46 | description: The docker image id SHA 47 | type: string 48 | required: 49 | - created 50 | - size 51 | - imageId 52 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/minProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minProperties validation", 4 | "schema": {"minProperties": 1}, 5 | "tests": [ 6 | { 7 | "description": "longer is valid", 8 | "data": {"foo": 1, "bar": 2}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too short is invalid", 18 | "data": {}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341-good.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | type: string 18 | default: 19 | description: generic error 20 | schema: 21 | type: string 22 | definitions: 23 | ExecuteValues: 24 | type: object 25 | properties: 26 | Value: 27 | $ref: "#/definitions/ExecuteValue" 28 | Array: 29 | type: array 30 | items: 31 | $ref: "#/definitions/ExecuteValues" 32 | 33 | ExecuteValue: 34 | type: object 35 | discriminator: ValueType 36 | required: 37 | - ValueType 38 | properties: 39 | ValueType: 40 | type: string 41 | Test: 42 | type: string 43 | ExecutableValueString: 44 | allOf: 45 | - $ref: '#/definitions/ExecuteValue' 46 | - type: object 47 | properties: 48 | something: 49 | type: string 50 | -------------------------------------------------------------------------------- /fixtures/bugs/61/multiple-refs.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "0.0.1", 5 | "title": "test of Swagger parameters with refs" 6 | }, 7 | "parameters": { 8 | "userId": { 9 | "name": "userId", 10 | "in": "path", 11 | "type": "string", 12 | "required": true 13 | }, 14 | "limit": { 15 | "name": "limit", 16 | "in": "query", 17 | "type": "integer", 18 | "format": "int64" 19 | } 20 | }, 21 | "paths": { 22 | "/foo": { 23 | "get": { 24 | "responses": { 25 | "200": { 26 | "description": "Successful" 27 | } 28 | } 29 | } 30 | }, 31 | "/bar": { 32 | "get": { 33 | "responses": { 34 | "200": { 35 | "description": "Successful" 36 | } 37 | } 38 | } 39 | }, 40 | "/users/{userId}": { 41 | "parameters": [{ 42 | "$ref": "#/parameters/userId" 43 | }, { 44 | "$ref": "#/parameters/limit" 45 | }], 46 | "get": { 47 | "responses": { 48 | "200": { 49 | "description": "Successful" 50 | } 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/maxProperties.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maxProperties validation", 4 | "schema": {"maxProperties": 2}, 5 | "tests": [ 6 | { 7 | "description": "shorter is valid", 8 | "data": {"foo": 1}, 9 | "valid": true 10 | }, 11 | { 12 | "description": "exact length is valid", 13 | "data": {"foo": 1, "bar": 2}, 14 | "valid": true 15 | }, 16 | { 17 | "description": "too long is invalid", 18 | "data": {"foo": 1, "bar": 2, "baz": 3}, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores arrays", 23 | "data": [1, 2, 3], 24 | "valid": true 25 | }, 26 | { 27 | "description": "ignores strings", 28 | "data": "foobar", 29 | "valid": true 30 | }, 31 | { 32 | "description": "ignores other non-objects", 33 | "data": 12, 34 | "valid": true 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /debug_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "os" 8 | "sync" 9 | "testing" 10 | 11 | "github.com/go-openapi/testify/v2/assert" 12 | ) 13 | 14 | var ( 15 | logMutex = &sync.Mutex{} 16 | ) 17 | 18 | func TestDebug(t *testing.T) { 19 | if !enableLongTests { 20 | skipNotify(t) 21 | t.SkipNow() 22 | } 23 | 24 | // standard lib t.TempDir() is still subject to an issue https://github.com/golang/go/issues/71544 25 | // Hence: usetesting linter disabled 26 | tmpFile, _ := os.CreateTemp("", "debug-test") //nolint:usetesting 27 | tmpName := tmpFile.Name() 28 | defer func() { 29 | Debug = false 30 | // mutex for -race 31 | logMutex.Unlock() 32 | os.Remove(tmpName) 33 | }() 34 | 35 | // mutex for -race 36 | logMutex.Lock() 37 | Debug = true 38 | debugOptions() 39 | defer func() { 40 | validateLogger.SetOutput(os.Stdout) 41 | }() 42 | 43 | validateLogger.SetOutput(tmpFile) 44 | 45 | debugLog("A debug") 46 | Debug = false 47 | tmpFile.Close() 48 | 49 | flushed, _ := os.Open(tmpName) 50 | buf := make([]byte, 500) 51 | _, _ = flushed.Read(buf) 52 | validateLogger.SetOutput(os.Stdout) 53 | assert.Contains(t, string(buf), "A debug") 54 | } 55 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341-2.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | $ref: '#/definitions/ExecuteValues' 18 | default: 19 | description: generic error 20 | schema: 21 | type: string 22 | definitions: 23 | ExecuteValues: 24 | type: object 25 | properties: 26 | Value: 27 | $ref: "#/definitions/ExecuteValue" 28 | Array: 29 | type: array 30 | items: 31 | $ref: "#/definitions/ExecuteValues" 32 | example: 33 | Array: 34 | - Array: 35 | - Value: 36 | Value: value 37 | ValueType: ExecuteValueString 38 | - Value: 39 | Value: true 40 | ValueType: ExecuteValueBoolean 41 | ExecuteValue: 42 | type: object 43 | discriminator: ValueType 44 | required: 45 | - ValueType 46 | #- Test 47 | properties: 48 | ValueType: 49 | type: string 50 | Test: 51 | type: string 52 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341-4.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | $ref: '#/definitions/ExecuteValues' 18 | default: 19 | description: generic error 20 | schema: 21 | type: string 22 | definitions: 23 | ExecuteValues: 24 | type: object 25 | properties: 26 | Value: 27 | $ref: "#/definitions/ExecuteValue" 28 | Array: 29 | type: array 30 | items: 31 | $ref: "#/definitions/ExecuteValues" 32 | default: 33 | Array: 34 | - Array: 35 | - Value: 36 | Value: value 37 | ValueType: ExecuteValueString 38 | - Value: 39 | Value: true 40 | ValueType: ExecuteValueBoolean 41 | ExecuteValue: 42 | type: object 43 | discriminator: ValueType 44 | required: 45 | - ValueType 46 | #- Test 47 | properties: 48 | ValueType: 49 | type: string 50 | Test: 51 | type: string 52 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-859-good.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "0.1.0" 5 | title: issue#859. Reference validation 6 | paths: 7 | /: 8 | post: 9 | parameters: 10 | - $ref: "#/parameters/rateLimit" 11 | responses: 12 | 200: 13 | description: "Success" 14 | get: 15 | parameters: 16 | - name: myparam 17 | in: body 18 | schema: 19 | $ref: '#/definitions/myparam' 20 | responses: 21 | default: 22 | description: the record 23 | schema: 24 | $ref: "#/definitions/record" 25 | 404: 26 | $ref: "#/responses/notFound" 27 | 200: 28 | description: "Success" 29 | schema: 30 | $ref: "#definitions/myoutput" 31 | 32 | parameters: 33 | rateLimit: 34 | name: X-Rate-Limit 35 | in: header 36 | type: integer 37 | format: int32 38 | 39 | responses: 40 | notFound: 41 | description: Not found 42 | schema: 43 | $ref: "#/definitions/record" 44 | 45 | definitions: 46 | record: 47 | type: object 48 | properties: 49 | createdAt: 50 | type: string 51 | format: date-time 52 | myparam: 53 | type: string 54 | myoutput: 55 | type: string 56 | -------------------------------------------------------------------------------- /fixtures/go-swagger/expansion/circularRefs.json: -------------------------------------------------------------------------------- 1 | { 2 | "definitions": { 3 | "brand": { 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string" 8 | } 9 | } 10 | }, 11 | "category": { 12 | "type": "object", 13 | "properties": { 14 | "children": { 15 | "type": "array", 16 | "items": { 17 | "$ref": "#/definitions/category" 18 | } 19 | } 20 | } 21 | }, 22 | "car": { 23 | "type": "object", 24 | "properties": { 25 | "id": { 26 | "type": "integer", 27 | "format": "int64" 28 | }, 29 | "make": { 30 | "type": "string" 31 | }, 32 | "similar": { 33 | "items": { 34 | "$ref": "#/definitions/car" 35 | } 36 | }, 37 | "notSimilar": { 38 | "additionalProperties": { 39 | "$ref": "#/definitions/car" 40 | } 41 | }, 42 | "oneCar": { 43 | "$ref": "#/definitions/car" 44 | }, 45 | "category": { 46 | "$ref": "#/definitions/category" 47 | }, 48 | "brand": { 49 | "$ref": "#/definitions/brand" 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | # $ref: '#/definitions/ExecuteValues' 18 | type: string 19 | default: 20 | description: generic error 21 | schema: 22 | type: string 23 | definitions: 24 | ExecuteValues: 25 | type: object 26 | properties: 27 | Value: 28 | $ref: "#/definitions/ExecuteValue" 29 | Array: 30 | type: array 31 | items: 32 | $ref: "#/definitions/ExecuteValues" 33 | example: 34 | Array: 35 | - Array: 36 | - Value: 37 | Value: value 38 | ValueType: ExecuteValueString 39 | - Value: 40 | Value: true 41 | ValueType: ExecuteValueBoolean 42 | ExecuteValue: 43 | type: object 44 | discriminator: ValueType 45 | required: 46 | - ValueType 47 | #- Test 48 | properties: 49 | ValueType: 50 | type: string 51 | Test: 52 | type: string 53 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341-3.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | # $ref: '#/definitions/ExecuteValues' 18 | type: string 19 | default: 20 | description: generic error 21 | schema: 22 | type: string 23 | definitions: 24 | ExecuteValues: 25 | type: object 26 | properties: 27 | Value: 28 | $ref: "#/definitions/ExecuteValue" 29 | Array: 30 | type: array 31 | items: 32 | $ref: "#/definitions/ExecuteValues" 33 | example: 34 | Array: 35 | - Array: 36 | - Value: 37 | Value: value 38 | ValueType: ExecuteValueString 39 | - Value: 40 | Value: true 41 | ValueType: ExecuteValueBoolean 42 | ExecuteValue: 43 | type: object 44 | discriminator: ValueType 45 | required: 46 | - ValueType 47 | - Test 48 | properties: 49 | ValueType: 50 | type: string 51 | Test: 52 | type: string 53 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/511/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: MyAPI 4 | description: some description 5 | version: "1.0.0" 6 | schemes: 7 | - http 8 | basePath: /v1 9 | consumes: 10 | - application/json 11 | produces: 12 | - application/json 13 | paths: 14 | /models: 15 | post: 16 | operationId: postModels 17 | summary: creates a new model 18 | description: | 19 | Creates a model..... 20 | tags: 21 | - Deployment 22 | consumes: 23 | - multipart/form-data 24 | parameters: 25 | - name: slugFile 26 | in: formData 27 | description: Payload with the model configuration. 28 | required: true 29 | type: file 30 | responses: 31 | 201: 32 | description: Model successfully accepted. 33 | headers: 34 | Location: 35 | description: Location header for the model 36 | type: string 37 | default: 38 | description: Unexpected error 39 | schema: 40 | $ref: '#/definitions/Error' 41 | 42 | definitions: 43 | Error: 44 | type: object 45 | properties: 46 | code: 47 | type: integer 48 | format: int32 49 | message: 50 | type: string 51 | fields: 52 | type: string 53 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-openapi/validate 2 | 3 | require ( 4 | github.com/go-openapi/analysis v0.24.1 5 | github.com/go-openapi/errors v0.22.4 6 | github.com/go-openapi/jsonpointer v0.22.3 7 | github.com/go-openapi/loads v0.23.2 8 | github.com/go-openapi/spec v0.22.1 9 | github.com/go-openapi/strfmt v0.25.0 10 | github.com/go-openapi/swag/conv v0.25.4 11 | github.com/go-openapi/swag/fileutils v0.25.4 12 | github.com/go-openapi/swag/jsonutils v0.25.4 13 | github.com/go-openapi/swag/stringutils v0.25.4 14 | github.com/go-openapi/testify/v2 v2.0.2 15 | go.yaml.in/yaml/v3 v3.0.4 16 | ) 17 | 18 | require ( 19 | github.com/go-openapi/jsonreference v0.21.3 // indirect 20 | github.com/go-openapi/swag/jsonname v0.25.1 // indirect 21 | github.com/go-openapi/swag/loading v0.25.1 // indirect 22 | github.com/go-openapi/swag/mangling v0.25.1 // indirect 23 | github.com/go-openapi/swag/typeutils v0.25.4 // indirect 24 | github.com/go-openapi/swag/yamlutils v0.25.1 // indirect 25 | github.com/go-viper/mapstructure/v2 v2.4.0 // indirect 26 | github.com/google/uuid v1.6.0 // indirect 27 | github.com/kr/pretty v0.3.1 // indirect 28 | github.com/oklog/ulid v1.3.1 // indirect 29 | go.mongodb.org/mongo-driver v1.17.6 // indirect 30 | golang.org/x/net v0.46.0 // indirect 31 | golang.org/x/text v0.30.0 // indirect 32 | ) 33 | 34 | go 1.24.0 35 | -------------------------------------------------------------------------------- /fixtures/validation/type-keyword-mismatch.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | description: Validation keyword type mismatch 4 | version: 0.0.1 5 | title: test 6 | paths: 7 | /test/{id}/string: 8 | get: 9 | parameters: 10 | - name: id 11 | in: path 12 | required: true 13 | type: string 14 | minimum: 1 15 | maximum: 5 16 | multipleOf: 33 17 | responses: 18 | '200': 19 | description: successful operation 20 | '500': 21 | description: Operation error 22 | 23 | /test/{id}/integer: 24 | get: 25 | parameters: 26 | - name: id 27 | in: path 28 | required: true 29 | type: integer 30 | minItems: 1 31 | maxItems: 5 32 | uniqueItems: true 33 | responses: 34 | '200': 35 | description: successful operation 36 | '500': 37 | description: Operation error 38 | 39 | /test/{id}/array: 40 | get: 41 | parameters: 42 | - name: id 43 | in: path 44 | required: true 45 | type: array 46 | minLength: 1 47 | maxLength: 5 48 | responses: 49 | '200': 50 | description: successful operation 51 | '500': 52 | description: Operation error 53 | -------------------------------------------------------------------------------- /rexp.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "maps" 8 | re "regexp" 9 | "sync" 10 | "sync/atomic" 11 | ) 12 | 13 | // Cache for compiled regular expressions 14 | var ( 15 | cacheMutex = &sync.Mutex{} 16 | reDict = atomic.Value{} // map[string]*re.Regexp 17 | ) 18 | 19 | func compileRegexp(pattern string) (*re.Regexp, error) { 20 | if cache, ok := reDict.Load().(map[string]*re.Regexp); ok { 21 | if r := cache[pattern]; r != nil { 22 | return r, nil 23 | } 24 | } 25 | 26 | r, err := re.Compile(pattern) 27 | if err != nil { 28 | return nil, err 29 | } 30 | cacheRegexp(r) 31 | return r, nil 32 | } 33 | 34 | func mustCompileRegexp(pattern string) *re.Regexp { 35 | if cache, ok := reDict.Load().(map[string]*re.Regexp); ok { 36 | if r := cache[pattern]; r != nil { 37 | return r 38 | } 39 | } 40 | 41 | r := re.MustCompile(pattern) 42 | cacheRegexp(r) 43 | return r 44 | } 45 | 46 | func cacheRegexp(r *re.Regexp) { 47 | cacheMutex.Lock() 48 | defer cacheMutex.Unlock() 49 | 50 | if cache, ok := reDict.Load().(map[string]*re.Regexp); !ok || cache[r.String()] == nil { 51 | newCache := map[string]*re.Regexp{ 52 | r.String(): r, 53 | } 54 | 55 | maps.Copy(newCache, cache) 56 | 57 | reDict.Store(newCache) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/453/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: 1.0.0 4 | title: 'Test' 5 | schemes: 6 | - http 7 | basePath: /v1/fancyAPI 8 | produces: 9 | - application/json 10 | consumes: 11 | - application/json 12 | 13 | definitions: 14 | in_object: 15 | type: object 16 | required: [test_id1, test_id2] 17 | properties: 18 | test_id1: 19 | type: integer 20 | test_id2: 21 | type: integer 22 | 23 | other_obj: 24 | type: object 25 | required: [type] 26 | discriminator: type 27 | additionalProperties: true 28 | description: some desc 29 | properties: 30 | type: 31 | type: string 32 | 33 | out_obj: 34 | allOf: 35 | - $ref: "#/definitions/other_obj" 36 | - type: object 37 | additionalProperties: true 38 | properties: 39 | fld1: 40 | type: integer 41 | minimum: 0 42 | maximim: 100 43 | fld2: 44 | $ref: "#/definitions/in_object" 45 | fld3: 46 | $ref: "#/definitions/in_object" 47 | fld5: 48 | $ref: "#/definitions/other_obj" 49 | 50 | paths: 51 | '/key/{id}': 52 | delete: 53 | parameters: 54 | - name: id 55 | in: path 56 | type: integer 57 | required: true 58 | responses: 59 | '200': 60 | description: OK 61 | -------------------------------------------------------------------------------- /post/defaulter.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Copyright 2018 go-swagger maintainers 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | package post 19 | 20 | import ( 21 | "github.com/go-openapi/validate" 22 | ) 23 | 24 | // ApplyDefaults applies defaults to the underlying data of the result. The data must be a JSON 25 | // struct as returned by json.Unmarshal. 26 | func ApplyDefaults(r *validate.Result) { 27 | fieldSchemata := r.FieldSchemata() 28 | for key, schemata := range fieldSchemata { 29 | LookForDefaultingScheme: 30 | for _, s := range schemata { 31 | if s.Default != nil { 32 | if _, found := key.Object()[key.Field()]; !found { 33 | key.Object()[key.Field()] = s.Default 34 | break LookForDefaultingScheme 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/162/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: '2' 4 | title: Server Rest API 5 | 6 | basePath: /rest/api/2/ 7 | schemes: 8 | - https 9 | consumes: 10 | - application/json 11 | produces: 12 | - application/json 13 | paths: 14 | '/search': 15 | get: 16 | operationId: getSearch 17 | parameters: 18 | - name: jql 19 | type: string 20 | in: query 21 | required: true 22 | responses: 23 | '200': 24 | description: Success 25 | schema: 26 | $ref: '#/definitions/SearchResponse' 27 | 28 | 29 | 30 | definitions: 31 | NotFound: 32 | type: object 33 | SearchResponse: 34 | type: object 35 | properties: 36 | issue: 37 | $ref: '#/definitions/Issue' 38 | 39 | Issue: 40 | type: object 41 | properties: 42 | assignee: 43 | $ref: '#/definitions/User' 44 | 45 | 46 | # Basic things 47 | User: 48 | type: object 49 | properties: 50 | key: 51 | type: string 52 | description: e.g. ldap username 53 | avatarUrls: 54 | $ref: '#/definitions/AvatarUrls' 55 | 56 | # this is what jira uses 57 | AvatarUrls: 58 | type: object 59 | properties: 60 | '48x48': 61 | type: string 62 | '32x32': 63 | type: string 64 | '24x24': 65 | type: string 66 | '16x16': 67 | type: string 68 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/maximum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "maximum validation", 4 | "schema": {"maximum": 3.0}, 5 | "tests": [ 6 | { 7 | "description": "below the maximum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 3.0, 14 | "valid": true 15 | }, 16 | { 17 | "description": "above the maximum is invalid", 18 | "data": 3.5, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "exclusiveMaximum validation", 30 | "schema": { 31 | "maximum": 3.0, 32 | "exclusiveMaximum": true 33 | }, 34 | "tests": [ 35 | { 36 | "description": "below the maximum is still valid", 37 | "data": 2.2, 38 | "valid": true 39 | }, 40 | { 41 | "description": "boundary point is invalid", 42 | "data": 3.0, 43 | "valid": false 44 | } 45 | ] 46 | } 47 | ] 48 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/minimum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "minimum validation", 4 | "schema": {"minimum": 1.1}, 5 | "tests": [ 6 | { 7 | "description": "above the minimum is valid", 8 | "data": 2.6, 9 | "valid": true 10 | }, 11 | { 12 | "description": "boundary point is valid", 13 | "data": 1.1, 14 | "valid": true 15 | }, 16 | { 17 | "description": "below the minimum is invalid", 18 | "data": 0.6, 19 | "valid": false 20 | }, 21 | { 22 | "description": "ignores non-numbers", 23 | "data": "x", 24 | "valid": true 25 | } 26 | ] 27 | }, 28 | { 29 | "description": "exclusiveMinimum validation", 30 | "schema": { 31 | "minimum": 1.1, 32 | "exclusiveMinimum": true 33 | }, 34 | "tests": [ 35 | { 36 | "description": "above the minimum is still valid", 37 | "data": 1.2, 38 | "valid": true 39 | }, 40 | { 41 | "description": "boundary point is invalid", 42 | "data": 1.1, 43 | "valid": false 44 | } 45 | ] 46 | } 47 | ] 48 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | linters: 3 | default: all 4 | disable: 5 | - depguard 6 | - funlen 7 | - godox 8 | - exhaustruct 9 | - nlreturn 10 | - nonamedreturns 11 | - noinlineerr 12 | - paralleltest 13 | - recvcheck 14 | - testpackage 15 | - tparallel 16 | - varnamelen 17 | - whitespace 18 | - wrapcheck 19 | - wsl 20 | - wsl_v5 21 | settings: 22 | dupl: 23 | threshold: 200 24 | goconst: 25 | min-len: 2 26 | min-occurrences: 3 27 | cyclop: 28 | max-complexity: 20 29 | gocyclo: 30 | min-complexity: 20 31 | exhaustive: 32 | default-signifies-exhaustive: true 33 | default-case-required: true 34 | lll: 35 | line-length: 180 36 | exclusions: 37 | generated: lax 38 | presets: 39 | - comments 40 | - common-false-positives 41 | - legacy 42 | - std-error-handling 43 | paths: 44 | - third_party$ 45 | - builtin$ 46 | - examples$ 47 | formatters: 48 | enable: 49 | - gofmt 50 | - goimports 51 | - gofumpt 52 | exclusions: 53 | generated: lax 54 | paths: 55 | - third_party$ 56 | - builtin$ 57 | - examples$ 58 | issues: 59 | # Maximum issues count per one linter. 60 | # Set to 0 to disable. 61 | # Default: 50 62 | max-issues-per-linter: 0 63 | # Maximum count of issues with the same text. 64 | # Set to 0 to disable. 65 | # Default: 3 66 | max-same-issues: 0 67 | -------------------------------------------------------------------------------- /.github/workflows/bump-release.yml: -------------------------------------------------------------------------------- 1 | name: Bump Release 2 | 3 | permissions: 4 | contents: read 5 | 6 | on: 7 | workflow_dispatch: 8 | inputs: 9 | bump-patch: 10 | description: Bump a patch version release 11 | type: boolean 12 | required: false 13 | default: true 14 | bump-minor: 15 | description: Bump a minor version release 16 | type: boolean 17 | required: false 18 | default: false 19 | bump-major: 20 | description: Bump a major version release 21 | type: boolean 22 | required: false 23 | default: false 24 | tag-message-title: 25 | description: Tag message title to prepend to the release notes 26 | required: false 27 | type: string 28 | tag-message-body: 29 | description: | 30 | Tag message body to prepend to the release notes. 31 | (use "|" to replace end of line). 32 | required: false 33 | type: string 34 | 35 | jobs: 36 | bump-release: 37 | permissions: 38 | contents: write 39 | uses: go-openapi/ci-workflows/.github/workflows/bump-release.yml@d0b50195d14745b9a9a8a41cf3bb7ecd874af37a # v0.1.1 40 | with: 41 | bump-patch: ${{ inputs.bump-patch }} 42 | bump-minor: ${{ inputs.bump-minor }} 43 | bump-major: ${{ inputs.bump-major }} 44 | tag-message-title: ${{ inputs.tag-message-title }} 45 | tag-message-body: ${{ inputs.tag-message-body }} 46 | secrets: inherit 47 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "invalid type for default", 4 | "schema": { 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "default": [] 9 | } 10 | } 11 | }, 12 | "tests": [ 13 | { 14 | "description": "valid when property is specified", 15 | "data": {"foo": 13}, 16 | "valid": true 17 | }, 18 | { 19 | "description": "still valid when the invalid default is used", 20 | "data": {}, 21 | "valid": true 22 | } 23 | ] 24 | }, 25 | { 26 | "description": "invalid string value for default", 27 | "schema": { 28 | "properties": { 29 | "bar": { 30 | "type": "string", 31 | "minLength": 4, 32 | "default": "bad" 33 | } 34 | } 35 | }, 36 | "tests": [ 37 | { 38 | "description": "valid when property is specified", 39 | "data": {"bar": "good"}, 40 | "valid": true 41 | }, 42 | { 43 | "description": "still valid when the invalid default is used", 44 | "data": {}, 45 | "valid": true 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /context_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "context" 8 | "fmt" 9 | "testing" 10 | 11 | "github.com/go-openapi/testify/v2/assert" 12 | ) 13 | 14 | func TestContext_ExtractOperationType(t *testing.T) { 15 | 16 | var testCases = []struct { 17 | Ctx context.Context //nolint: containedctx 18 | ExpectedOpType operationType 19 | }{ 20 | { 21 | Ctx: WithOperationRequest(context.Background()), 22 | ExpectedOpType: request, 23 | }, 24 | { 25 | Ctx: WithOperationResponse(context.Background()), 26 | ExpectedOpType: response, 27 | }, 28 | { 29 | Ctx: context.Background(), 30 | ExpectedOpType: none, 31 | }, 32 | { 33 | Ctx: context.WithValue(context.Background(), validateCtxKey("dummy"), "dummy val"), 34 | ExpectedOpType: none, 35 | }, 36 | { 37 | Ctx: context.WithValue(context.Background(), operationTypeKey, "dummy val"), 38 | ExpectedOpType: none, 39 | }, 40 | { 41 | Ctx: context.WithValue(context.Background(), operationTypeKey, operationType("dummy val")), 42 | ExpectedOpType: none, 43 | }, 44 | } 45 | 46 | for idx, toPin := range testCases { 47 | tc := toPin 48 | t.Run(fmt.Sprintf("TestCase #%d", idx), func(t *testing.T) { 49 | t.Parallel() 50 | op := extractOperationType(tc.Ctx) 51 | assert.Equal(t, tc.ExpectedOpType, op) 52 | }) 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /fixtures/bugs/1341/fixture-1341-5.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Title 4 | description: some description 5 | contact: 6 | name: John Doe 7 | url: https://www.acme.com/support 8 | email: support@acme.com 9 | version: "1.0.0" 10 | paths: 11 | /: 12 | get: 13 | responses: 14 | 200: 15 | description: Example path 16 | schema: 17 | #$ref: '#/definitions/ExecuteValues' 18 | type: string 19 | default: 20 | description: generic error 21 | schema: 22 | type: string 23 | definitions: 24 | ExecuteValues: 25 | description: recursive definition 26 | type: object 27 | properties: 28 | Value: 29 | $ref: "#/definitions/ExecuteValue" 30 | Array: 31 | description: array definition 32 | type: array 33 | items: 34 | $ref: "#/definitions/ExecuteValues" 35 | default: 36 | Array: 37 | - Array: 38 | - Value: 39 | Value: value 40 | ValueType: ExecuteValueString 41 | - Value: 42 | Value: true 43 | ValueType: ExecuteValueBoolean 44 | ExecuteValue: 45 | description: non-recursive definition 46 | type: object 47 | discriminator: ValueType 48 | required: 49 | - ValueType 50 | - Test 51 | properties: 52 | ValueType: 53 | description: the type of the value 54 | type: string 55 | Test: 56 | description: a test 57 | type: string 58 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-581.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: 'fixture for issue #581' 5 | version: '1.0' 6 | description: | 7 | test verification of overflow on min/max boundary 8 | reproduces the initial reported case,with schema and $refs 9 | 10 | produces: 11 | - application/json 12 | paths: 13 | /fixture: 14 | get: 15 | operationId: op1 16 | parameters: 17 | - name: myid 18 | in: query 19 | schema: 20 | $ref: '#/definitions/myId' 21 | responses: 22 | 200: 23 | description: 'response exercising integer boundaries' 24 | schema: 25 | $ref: '#/definitions/someIds' 26 | 27 | definitions: 28 | myId: 29 | type: object 30 | properties: 31 | uint8: 32 | type: integer 33 | minimum: 0 34 | maximum: 255 35 | # Error: default does not validate against boundaries 36 | default: 256 37 | int64: 38 | type: integer 39 | minimum: -9223372036854775808 40 | # Error: maximum is not an int64 41 | maximum: 9223372036854775807000 42 | uint64: 43 | type: integer 44 | minimum: -9223372036854775807000 45 | maximum: 18446744073709551615 46 | uint64-wrong: 47 | type: integer 48 | minimum: 0 49 | maximum: 18446744073709551616 50 | someIds: 51 | type: object 52 | properties: 53 | smallId: 54 | type: integer 55 | minimum: 0 56 | maximum: 12 57 | -------------------------------------------------------------------------------- /pools_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate_test 5 | 6 | import ( 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/go-openapi/loads" 11 | "github.com/go-openapi/strfmt" 12 | "github.com/go-openapi/testify/v2/require" 13 | "github.com/go-openapi/validate" 14 | ) 15 | 16 | func Test_ParallelPool(t *testing.T) { 17 | fixture1 := filepath.Join("fixtures", "bugs", "1429", "swagger.yaml") 18 | fixture2 := filepath.Join("fixtures", "bugs", "2866", "2866.yaml") 19 | fixture3 := filepath.Join("fixtures", "bugs", "43", "fixture-43.yaml") 20 | 21 | t.Run("should validate in parallel", func(t *testing.T) { 22 | for range 20 { 23 | t.Run("validating fixture 1", func(t *testing.T) { 24 | t.Parallel() 25 | 26 | doc1, err := loads.Spec(fixture1) 27 | require.NoError(t, err) 28 | require.NotNil(t, doc1) 29 | require.NoError(t, validate.Spec(doc1, strfmt.Default)) 30 | }) 31 | 32 | t.Run("validating fixture 2", func(t *testing.T) { 33 | t.Parallel() 34 | 35 | doc2, err := loads.Spec(fixture2) 36 | require.NoError(t, err) 37 | require.NotNil(t, doc2) 38 | require.NoError(t, validate.Spec(doc2, strfmt.Default)) 39 | }) 40 | 41 | t.Run("validating fixture 2", func(t *testing.T) { 42 | t.Parallel() 43 | 44 | doc3, err := loads.Spec(fixture3) 45 | require.NoError(t, err) 46 | require.NotNil(t, doc3) 47 | require.NoError(t, validate.Spec(doc3, strfmt.Default)) 48 | }) 49 | } 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /schema_option_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/go-openapi/testify/v2/require" 10 | ) 11 | 12 | func TestSchemaOptions(t *testing.T) { 13 | t.Run("EnableObjectArrayTypeCheck", func(t *testing.T) { 14 | opts := &SchemaValidatorOptions{} 15 | setter := EnableObjectArrayTypeCheck(true) 16 | setter(opts) 17 | require.True(t, opts.EnableObjectArrayTypeCheck) 18 | }) 19 | 20 | t.Run("skipSchemataResult", func(t *testing.T) { 21 | opts := &SchemaValidatorOptions{} 22 | setter := WithSkipSchemataResult(true) 23 | setter(opts) 24 | require.True(t, opts.skipSchemataResult) 25 | }) 26 | 27 | t.Run("default Options()", func(t *testing.T) { 28 | opts := &SchemaValidatorOptions{} 29 | setters := opts.Options() 30 | 31 | target := &SchemaValidatorOptions{} 32 | for _, apply := range setters { 33 | apply(target) 34 | } 35 | require.Equal(t, opts, target) 36 | }) 37 | 38 | t.Run("all set Options()", func(t *testing.T) { 39 | opts := &SchemaValidatorOptions{ 40 | EnableObjectArrayTypeCheck: true, 41 | EnableArrayMustHaveItemsCheck: true, 42 | recycleValidators: true, 43 | recycleResult: true, 44 | skipSchemataResult: true, 45 | } 46 | setters := opts.Options() 47 | 48 | target := &SchemaValidatorOptions{} 49 | for _, apply := range setters { 50 | apply(target) 51 | } 52 | require.Equal(t, opts, target) 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /fixtures/go-swagger/expansion/circularSpec.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | title: Swagger Sample 5 | description: Sample API Playground. 6 | version: 1.0.0 7 | basePath: /v1 8 | schemes: 9 | - http 10 | consumes: 11 | - application/vdn.sample.v1+json 12 | produces: 13 | - application/vdn.sample.v1+json 14 | 15 | paths: 16 | /books: 17 | get: 18 | summary: List all books 19 | operationId: listBooks 20 | tags: 21 | - books 22 | responses: 23 | 200: 24 | headers: 25 | Link: 26 | type: string 27 | description: An array of books 28 | schema: 29 | type: array 30 | items: 31 | $ref: "#/definitions/Book" 32 | default: 33 | description: generic error response 34 | schema: 35 | $ref: "#/definitions/Error" 36 | 37 | definitions: 38 | Book: 39 | type: object 40 | required: 41 | - title 42 | - summary 43 | properties: 44 | title: 45 | type: string 46 | example: Winnie the Pooh 47 | summary: 48 | type: string 49 | example: Famous children's book 50 | related_books: 51 | type: array 52 | items: 53 | $ref: "#/definitions/Book" 54 | 55 | Error: 56 | type: object 57 | readOnly: true 58 | properties: 59 | code: 60 | type: integer 61 | format: int64 62 | example: 400 63 | message: 64 | type: string 65 | example: Unexpected error 66 | required: 67 | - message 68 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/required.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "required validation", 4 | "schema": { 5 | "properties": { 6 | "foo": {}, 7 | "bar": {} 8 | }, 9 | "required": ["foo"] 10 | }, 11 | "tests": [ 12 | { 13 | "description": "present required property is valid", 14 | "data": {"foo": 1}, 15 | "valid": true 16 | }, 17 | { 18 | "description": "non-present required property is invalid", 19 | "data": {"bar": 1}, 20 | "valid": false 21 | }, 22 | { 23 | "description": "ignores arrays", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "ignores strings", 29 | "data": "", 30 | "valid": true 31 | }, 32 | { 33 | "description": "ignores other non-objects", 34 | "data": 12, 35 | "valid": true 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "required default validation", 41 | "schema": { 42 | "properties": { 43 | "foo": {} 44 | } 45 | }, 46 | "tests": [ 47 | { 48 | "description": "not required by default", 49 | "data": {}, 50 | "valid": true 51 | } 52 | ] 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1171/swagger.yaml: -------------------------------------------------------------------------------- 1 | # In this one we make sure arrays without items are detected by validation 2 | # Conversely, objects with items are detected with fixture for issue #1238 3 | swagger: '2.0' 4 | info: 5 | title: issue-1171 6 | version: 0.0.1 7 | license: 8 | name: MIT 9 | host: localhost:8081 10 | basePath: /api/v1 11 | schemes: 12 | - http 13 | consumes: 14 | - application/json 15 | produces: 16 | - application/json 17 | paths: 18 | '/servers/{server_id}/zones': 19 | get: 20 | operationId: listZones 21 | tags: 22 | - zones 23 | parameters: 24 | - name: server_id 25 | in: path 26 | required: true 27 | type: string 28 | responses: 29 | '200': 30 | description: An array of Zones 31 | schema: 32 | $ref: '#/definitions/Zones' 33 | 34 | '/servers/{server_id}/zones/{zone_id}': 35 | get: 36 | operationId: listZone 37 | tags: 38 | - zones 39 | parameters: 40 | - name: server_id 41 | in: path 42 | required: true 43 | type: string 44 | - name: zone_id 45 | type: string 46 | in: path 47 | required: true 48 | responses: 49 | '200': 50 | description: A Zone 51 | schema: 52 | $ref: '#/definitions/Zone' 53 | 54 | 55 | definitions: 56 | Zones: 57 | type: array 58 | properties: 59 | name: 60 | type: string 61 | 62 | Zone: 63 | type: array 64 | items: 65 | name: 66 | type: string 67 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/740/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: "2.0" 2 | 3 | info: 4 | title: allOf 5 | description: allOf bug example 6 | version: 0.0.1 7 | 8 | schemes: 9 | - http 10 | 11 | consumes: 12 | - application/json 13 | produces: 14 | - application/json 15 | 16 | definitions: 17 | 18 | Lol: 19 | type: object 20 | required: 21 | - xxx 22 | - yyy 23 | - zzz 24 | properties: 25 | xxx: 26 | type: string 27 | yyy: 28 | type: integer 29 | zzz: 30 | type: boolean 31 | 32 | Foo: 33 | type: object 34 | properties: 35 | fauna: 36 | $ref: "#/definitions/Lol" 37 | flora: 38 | $ref: "#/definitions/Lol" 39 | fungi: 40 | $ref: "#/definitions/Lol" 41 | 42 | Bar: 43 | type: object 44 | allOf: 45 | - $ref: "#/definitions/Foo" 46 | 47 | Baz: 48 | type: object 49 | properties: 50 | squirrel: 51 | type: string 52 | owl: 53 | type: string 54 | fox: 55 | type: string 56 | 57 | Awol: 58 | type: object 59 | allOf: 60 | - $ref: "#/definitions/Bar" 61 | - $ref: "#/definitions/Baz" 62 | 63 | paths: 64 | 65 | /awol: 66 | put: 67 | operationId: setAwol 68 | summary: Set Awol 69 | parameters: 70 | - name: awol 71 | in: body 72 | required: true 73 | description: Awol 74 | schema: 75 | $ref: "#/definitions/Awol" 76 | responses: 77 | 201: 78 | description: Awol set 79 | schema: 80 | $ref: "#/definitions/Awol" 81 | -------------------------------------------------------------------------------- /.github/DCO.md: -------------------------------------------------------------------------------- 1 | # Developer's Certificate of Origin 2 | 3 | ``` 4 | Developer Certificate of Origin 5 | Version 1.1 6 | 7 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 8 | 660 York Street, Suite 102, 9 | San Francisco, CA 94110 USA 10 | 11 | Everyone is permitted to copy and distribute verbatim copies of this 12 | license document, but changing it is not allowed. 13 | 14 | 15 | Developer's Certificate of Origin 1.1 16 | 17 | By making a contribution to this project, I certify that: 18 | 19 | (a) The contribution was created in whole or in part by me and I 20 | have the right to submit it under the open source license 21 | indicated in the file; or 22 | 23 | (b) The contribution is based upon previous work that, to the best 24 | of my knowledge, is covered under an appropriate open source 25 | license and I have the right under that license to submit that 26 | work with modifications, whether created in whole or in part 27 | by me, under the same open source license (unless I am 28 | permitted to submit under a different license), as indicated 29 | in the file; or 30 | 31 | (c) The contribution was provided directly to me by some other 32 | person who certified (a), (b) or (c) and I have not modified 33 | it. 34 | 35 | (d) I understand and agree that this project and the contribution 36 | are public and that a record of the contribution (including all 37 | personal information I submit with it, including my sign-off) is 38 | maintained indefinitely and may be redistributed consistent with 39 | this project or the open source license(s) involved. 40 | ``` 41 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/252/swagger.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "localhost", 3 | "schemes": ["https"], 4 | "swagger": "2.0", 5 | "produces": ["application/json"], 6 | "consumes": ["application/json"], 7 | "info": { 8 | "title": "Soda Booth", 9 | "version": "2.0" 10 | }, 11 | "paths": { 12 | "/v2/locations/{location_id}/transactions": { 13 | "get": { 14 | "summary": "Sodas", 15 | "tags": ["Sodas"], 16 | "description": "Lists sodas for a particular location.", 17 | "parameters": [{ 18 | "name": "Authorization", 19 | "required": true, 20 | "type": "string", 21 | "in": "header" 22 | }, { 23 | "name": "location_id", 24 | "required": true, 25 | "type": "string", 26 | "in": "path" 27 | }], 28 | "responses": { 29 | "200": { 30 | "schema": { 31 | "$ref": "#/definitions/SodaResponse" 32 | }, 33 | "description": "Success" 34 | } 35 | }, 36 | "operationId": "List" 37 | } 38 | } 39 | }, 40 | "definitions": { 41 | "SodaBrand": { 42 | "description": "", 43 | "enum": [ 44 | "OTHER_BRAND", 45 | "PEPSI", 46 | "COKE", 47 | "CACTUS_COOLER", 48 | "JOLT" 49 | ], 50 | "type": "string" 51 | }, 52 | "SodaResponse": { 53 | "description": "", 54 | "properties": { 55 | "soda_brand": { 56 | "$ref": "#/definitions/SodaBrand" 57 | } 58 | }, 59 | "type": "object" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /fixtures/bugs/102/fixture-102.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "My API", 5 | "version": "1.0.0", 6 | "title": "my api", 7 | "contact": { 8 | "email": "me@myorg.com" 9 | }, 10 | "license": { 11 | "name": "my org" 12 | } 13 | }, 14 | "host": "127.0.0.1", 15 | "basePath": "/", 16 | "tags": [], 17 | "schemes": [ 18 | "https" 19 | ], 20 | "paths": { 21 | "/api/v1/endpoint": { 22 | "post": { 23 | "summary": "my endpoint", 24 | "description": "Accessible to . ", 25 | "operationId": "ep1", 26 | "consumes": [ 27 | "application/json" 28 | ], 29 | "produces": [ 30 | "application/json" 31 | ], 32 | "parameters": [ 33 | 34 | ], 35 | "responses": { 36 | "200": { 37 | "description": "Operation successful", 38 | "schema": { 39 | "$ref": "#/definitions/Error" 40 | } 41 | } 42 | }, 43 | "security": [] 44 | } 45 | } 46 | }, 47 | "definitions": { 48 | "Error": { 49 | "type": "object", 50 | "properties": { 51 | "errorCode": { 52 | "type": "string", 53 | "format": "string" 54 | }, 55 | "errorMessage": { 56 | "type": "string", 57 | "format": "string" 58 | }, 59 | "warning": { 60 | "type": "string" 61 | }, 62 | "child-errors": { 63 | "type": "array", 64 | "items": { 65 | "$ref": "#/definitions/Error" 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-859.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "0.1.0" 5 | title: issue#859. Reference validation 6 | paths: 7 | /: 8 | post: 9 | parameters: 10 | # error 11 | - $ref: "#/parameters/rateLimit" 12 | - name: myparam 13 | in: query 14 | type: string 15 | responses: 16 | 200: 17 | description: "Success" 18 | get: 19 | parameters: 20 | - $ref: "#/parameters/rateLimit" # <-- error: mispelled reference cannot resolve 21 | - name: myparam 22 | in: query 23 | schema: 24 | $ref: '#/definitions/myparam' # <- error : mispelled reference cannot resolve 25 | responses: 26 | default: 27 | description: the record 28 | schema: 29 | $ref: "#/definitions/record" # <- error : mispelled reference cannot resolve 30 | 404: 31 | $ref: "#/responses/notFound" 32 | 200: 33 | description: "Success" 34 | schema: 35 | $ref: "#definitions/myoutput" # <- error : mispelled reference cannot resolve 36 | 37 | parameters: 38 | rateLimits: 39 | name: X-Rate-Limit 40 | in: header 41 | type: integer 42 | format: int32 43 | 44 | responses: 45 | notFound: 46 | description: Not found 47 | schema: 48 | $ref: "#/definitions/record" # <- error : mispelled reference cannot resolve 49 | 50 | definitions: 51 | records: 52 | type: object 53 | properties: 54 | createdAt: 55 | type: string 56 | format: date-time 57 | myparams: 58 | type: string 59 | myoutputs: 60 | type: string 61 | -------------------------------------------------------------------------------- /post/prune.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Copyright 2018 go-swagger maintainers 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); 7 | // you may not use this file except in compliance with the License. 8 | // You may obtain a copy of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, 14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | // See the License for the specific language governing permissions and 16 | // limitations under the License. 17 | 18 | package post 19 | 20 | import ( 21 | "github.com/go-openapi/validate" 22 | ) 23 | 24 | // Prune recursively removes all non-specified fields from the underlying data of the result. 25 | // The data must be a JSON struct as returned by json.Unmarshal. 26 | func Prune(r *validate.Result) { 27 | prune(r.Data(), r) 28 | } 29 | 30 | func prune(data any, result *validate.Result) { 31 | switch obj := data.(type) { 32 | case map[string]any: 33 | pruneObject(obj, result) 34 | for _, val := range obj { 35 | prune(val, result) 36 | } 37 | case []any: 38 | for _, item := range obj { 39 | prune(item, result) 40 | } 41 | } 42 | } 43 | 44 | func pruneObject(obj map[string]any, result *validate.Result) { 45 | fieldSchemata := result.FieldSchemata() 46 | for field := range obj { 47 | if schemata, ok := fieldSchemata[validate.NewFieldKey(obj, field)]; !ok || len(schemata) == 0 { 48 | delete(obj, field) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-859-2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: "2.0" 3 | info: 4 | version: "0.1.0" 5 | title: issue#859. Reference validation 6 | description: more exercising on $ref recursion,default response,items 7 | paths: 8 | /: 9 | post: 10 | parameters: 11 | - $ref: "#/parameters/rateLimit" 12 | responses: 13 | 200: 14 | description: "Success" 15 | get: 16 | parameters: 17 | - name: myparam 18 | in: body 19 | schema: 20 | $ref: '#/definitions/myparam' 21 | responses: 22 | default: 23 | description: the record 24 | schema: 25 | $ref: "#/definitions/record" 26 | 404: 27 | $ref: "#/responses/notFound" 28 | 200: 29 | description: "Success" 30 | schema: 31 | $ref: "#definitions/myoutput" 32 | 201: 33 | description: "Success" 34 | schema: 35 | $ref: "#definitions/myoutput" 36 | 37 | parameters: 38 | rateLimit: 39 | name: X-Rate-Limit 40 | in: header 41 | type: integer 42 | format: int32 43 | 44 | responses: 45 | notFound: 46 | description: Not found 47 | schema: 48 | $ref: "#/definitions/record" 49 | 50 | definitions: 51 | record: 52 | type: object 53 | properties: 54 | createdAt: 55 | type: string 56 | format: date-time 57 | myparam: 58 | type: array 59 | items: 60 | $ref: "#/definitions/myitems" 61 | myoutput: 62 | type: array 63 | items: 64 | # Error: unresolved 65 | $ref: "#/definitions/myitem" 66 | myitems: 67 | type: object 68 | properties: 69 | ident: 70 | type: string 71 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1111/arrayParam.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "host": "localhost", 4 | "info": { 5 | "description": "", 6 | "version": "", 7 | "title": "", 8 | "termsOfService": "" 9 | }, 10 | "basePath": "/api/v1/", 11 | "paths": { 12 | "/clusters/elasticsearch/{cluster_id}/instances/{instance_ids}/_start": { 13 | "post": { 14 | "operationId": "start-es-cluster-instances", 15 | "parameters": [ 16 | { 17 | "name": "cluster_id", 18 | "in": "path", 19 | "description": "Identifier for the Elasticsearch cluster", 20 | "required": true, 21 | "type": "string" 22 | }, 23 | { 24 | "name": "instance_ids", 25 | "in": "path", 26 | "description": "Optional comma-delimited list of instance identifiers of the Elasticsearch cluster, otherwise will apply to all instances", 27 | "required": true, 28 | "type": "array", 29 | "items": { 30 | "type": "string" 31 | }, 32 | "collectionFormat": "csv" 33 | } 34 | ], 35 | "responses": { 36 | "202": { 37 | "description": "The start command was issued successfully, use the \"GET\" command on the /{cluster_id} resource to monitor progress" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /fixtures/bugs/1621/parameters.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | 3 | RequiredGiantSwarmAuthorizationHeader: 4 | name: Authorization 5 | type: string 6 | in: header 7 | required: true 8 | description: As described in the [authentication](#section/Authentication) section 9 | 10 | ClusterIdPathParameter: 11 | name: cluster_id 12 | in: path 13 | required: true 14 | type: string 15 | description: Cluster ID 16 | 17 | UserEmailPathParameter: 18 | name: email 19 | in: path 20 | required: true 21 | type: string 22 | description: The user's email address 23 | 24 | OrganizationIdPathParameter: 25 | name: organization_id 26 | in: path 27 | required: true 28 | type: string 29 | description: | 30 | An ID for the organization. 31 | This ID must be unique and match this regular 32 | expression: ^[a-z0-9_]{4,30}$ 33 | 34 | XRequestIDHeader: 35 | name: X-Request-ID 36 | in: header 37 | type: string 38 | required: false 39 | description: | 40 | A randomly generated key that can be used to track a request throughout 41 | services of Giant Swarm. 42 | 43 | XGiantSwarmActivityHeader: 44 | name: X-Giant-Swarm-Activity 45 | in: header 46 | type: string 47 | required: false 48 | description: | 49 | Name of an activity to track, like "list-clusters". This allows to 50 | analyze several API requests sent in context and gives an idea on 51 | the purpose. 52 | 53 | XGiantSwarmCmdLineHeader: 54 | name: X-Giant-Swarm-CmdLine 55 | in: header 56 | type: string 57 | required: false 58 | description: | 59 | If activity has been issued by a CLI, this header can contain the 60 | command line 61 | 62 | -------------------------------------------------------------------------------- /context.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "context" 8 | ) 9 | 10 | // validateCtxKey is the key type of context key in this pkg 11 | type validateCtxKey string 12 | 13 | const ( 14 | operationTypeKey validateCtxKey = "operationTypeKey" 15 | ) 16 | 17 | type operationType string 18 | 19 | const ( 20 | request operationType = "request" 21 | response operationType = "response" 22 | none operationType = "none" // not specified in ctx 23 | ) 24 | 25 | var operationTypeEnum = []operationType{request, response, none} 26 | 27 | // WithOperationRequest returns a new context with operationType request 28 | // in context value 29 | func WithOperationRequest(ctx context.Context) context.Context { 30 | return withOperation(ctx, request) 31 | } 32 | 33 | // WithOperationResponse returns a new context with operationType response 34 | // in context value 35 | func WithOperationResponse(ctx context.Context) context.Context { 36 | return withOperation(ctx, response) 37 | } 38 | 39 | func withOperation(ctx context.Context, operation operationType) context.Context { 40 | return context.WithValue(ctx, operationTypeKey, operation) 41 | } 42 | 43 | // extractOperationType extracts the operation type from ctx 44 | // if not specified or of unknown value, return none operation type 45 | func extractOperationType(ctx context.Context) operationType { 46 | v := ctx.Value(operationTypeKey) 47 | if v == nil { 48 | return none 49 | } 50 | res, ok := v.(operationType) 51 | if !ok { 52 | return none 53 | } 54 | // validate the value is in operation enum 55 | if err := Enum("", "", res, operationTypeEnum); err != nil { 56 | return none 57 | } 58 | return res 59 | } 60 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/multipleOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "by int", 4 | "schema": {"multipleOf": 2}, 5 | "tests": [ 6 | { 7 | "description": "int by int", 8 | "data": 10, 9 | "valid": true 10 | }, 11 | { 12 | "description": "int by int fail", 13 | "data": 7, 14 | "valid": false 15 | }, 16 | { 17 | "description": "ignores non-numbers", 18 | "data": "foo", 19 | "valid": true 20 | } 21 | ] 22 | }, 23 | { 24 | "description": "by number", 25 | "schema": {"multipleOf": 1.5}, 26 | "tests": [ 27 | { 28 | "description": "zero is multiple of anything", 29 | "data": 0, 30 | "valid": true 31 | }, 32 | { 33 | "description": "4.5 is multiple of 1.5", 34 | "data": 4.5, 35 | "valid": true 36 | }, 37 | { 38 | "description": "35 is not multiple of 1.5", 39 | "data": 35, 40 | "valid": false 41 | } 42 | ] 43 | }, 44 | { 45 | "description": "by small number", 46 | "schema": {"multipleOf": 0.0001}, 47 | "tests": [ 48 | { 49 | "description": "0.0075 is multiple of 0.0001", 50 | "data": 0.0075, 51 | "valid": true 52 | }, 53 | { 54 | "description": "0.00751 is not multiple of 0.0001", 55 | "data": 0.00751, 56 | "valid": false 57 | } 58 | ] 59 | } 60 | ] 61 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-1238.yaml: -------------------------------------------------------------------------------- 1 | # This spec should be correctly detected as invalid 2 | swagger: '2.0' 3 | info: 4 | title: issue-1238 5 | version: 0.0.1 6 | license: 7 | name: MIT 8 | host: localhost:8081 9 | basePath: /api/v1 10 | schemes: 11 | - http 12 | consumes: 13 | - application/json 14 | produces: 15 | - application/json 16 | paths: 17 | '/servers/{server_id}/zones': 18 | get: 19 | operationId: listZones 20 | tags: 21 | - zones 22 | parameters: 23 | - name: server_id 24 | in: path 25 | required: true 26 | type: string 27 | responses: 28 | '200': 29 | description: An array of Zones 30 | schema: 31 | $ref: '#/definitions/Zones' 32 | 33 | '/servers/{server_id}/zones/{zone_id}': 34 | get: 35 | operationId: listZone 36 | tags: 37 | - zones 38 | parameters: 39 | - name: server_id 40 | in: path 41 | required: true 42 | type: string 43 | - name: zone_id 44 | type: string 45 | in: path 46 | required: true 47 | responses: 48 | '200': 49 | description: A Zone 50 | schema: 51 | $ref: '#/definitions/Zone' 52 | 53 | 54 | definitions: 55 | Zones: 56 | type: array 57 | items: 58 | $ref: '#/definitions/Zone' 59 | 60 | Zone: 61 | type: object 62 | properties: 63 | name: 64 | type: string 65 | RR: 66 | $ref: '#/definitions/RRSets' 67 | 68 | RRSets: 69 | # Declaring items for an object should be correctly assessed as invalid and not trigger a panic (issue#1238) 70 | type: object 71 | items: 72 | $ref: '#/definitions/RRSet' 73 | 74 | RRSet: 75 | properties: 76 | name: 77 | type: string 78 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/1238/swagger.yaml: -------------------------------------------------------------------------------- 1 | # This spec should be correctly detected as invalid 2 | swagger: '2.0' 3 | info: 4 | title: issue-1238 5 | version: 0.0.1 6 | license: 7 | name: MIT 8 | host: localhost:8081 9 | basePath: /api/v1 10 | schemes: 11 | - http 12 | consumes: 13 | - application/json 14 | produces: 15 | - application/json 16 | paths: 17 | '/servers/{server_id}/zones': 18 | get: 19 | operationId: listZones 20 | tags: 21 | - zones 22 | parameters: 23 | - name: server_id 24 | in: path 25 | required: true 26 | type: string 27 | responses: 28 | '200': 29 | description: An array of Zones 30 | schema: 31 | $ref: '#/definitions/Zones' 32 | 33 | '/servers/{server_id}/zones/{zone_id}': 34 | get: 35 | operationId: listZone 36 | tags: 37 | - zones 38 | parameters: 39 | - name: server_id 40 | in: path 41 | required: true 42 | type: string 43 | - name: zone_id 44 | type: string 45 | in: path 46 | required: true 47 | responses: 48 | '200': 49 | description: A Zone 50 | schema: 51 | $ref: '#/definitions/Zone' 52 | 53 | 54 | definitions: 55 | Zones: 56 | type: array 57 | items: 58 | $ref: '#/definitions/Zone' 59 | 60 | Zone: 61 | type: object 62 | properties: 63 | name: 64 | type: string 65 | RR: 66 | $ref: '#/definitions/RRSets' 67 | 68 | RRSets: 69 | # Declaring items for an object should be correctly assessed as invalid and not trigger a panic (issue#1238) 70 | type: object 71 | items: 72 | $ref: '#/definitions/RRSet' 73 | 74 | RRSet: 75 | properties: 76 | name: 77 | type: string 78 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/628/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | 3 | info: 4 | version: "1.0.0" 5 | title: Private to-do list 6 | description: | 7 | A very simple api description that makes a json only API to submit to do's. 8 | 9 | produces: 10 | - application/json 11 | 12 | consumes: 13 | - application/json 14 | 15 | paths: 16 | /collection: 17 | get: 18 | operationId: collection 19 | parameters: 20 | - name: "workspace_id" 21 | in: "query" 22 | required: true 23 | type: "array" 24 | items: 25 | type: "string" 26 | format: "uuid" 27 | responses: 28 | '200': 29 | description: returns single item 30 | headers: 31 | 'X-Request-Id': 32 | required: true 33 | type: "array" 34 | items: 35 | type: "string" 36 | format: "uuid" 37 | /single: 38 | get: 39 | operationId: single 40 | parameters: 41 | - name: "workspace_id" 42 | in: "query" 43 | required: true 44 | type: "string" 45 | format: "uuid" 46 | responses: 47 | '200': 48 | description: returns single item 49 | headers: 50 | 'X-Request-Id': 51 | type: string 52 | required: true 53 | format: uuid 54 | /{id}: 55 | get: 56 | operationId: details 57 | parameters: 58 | - name: "id" 59 | in: "path" 60 | required: true 61 | type: "string" 62 | format: "uuid" 63 | 64 | definitions: 65 | genericResource: 66 | description: generic resource 67 | properties: 68 | meta: 69 | type: string 70 | required: 71 | - meta 72 | additionalProperties: 73 | type: object 74 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | day: "friday" 8 | open-pull-requests-limit: 2 # <- default is 5 9 | groups: # <- group all github actions updates in a single PR 10 | # 1. development-dependencies are auto-merged 11 | development-dependencies: 12 | patterns: 13 | - '*' 14 | 15 | - package-ecosystem: "gomod" 16 | # We define 4 groups of dependencies to regroup update pull requests: 17 | # - development (e.g. test dependencies) 18 | # - go-openapi updates 19 | # - golang.org (e.g. golang.org/x/... packages) 20 | # - other dependencies (direct or indirect) 21 | # 22 | # * All groups are checked once a week and each produce at most 1 PR. 23 | # * All dependabot PRs are auto-approved 24 | # 25 | # Auto-merging policy, when requirements are met: 26 | # 1. development-dependencies are auto-merged 27 | # 2. golang.org-dependencies are auto-merged 28 | # 3. go-openapi patch updates are auto-merged. Minor/major version updates require a manual merge. 29 | # 4. other dependencies require a manual merge 30 | directory: "/" 31 | schedule: 32 | interval: "weekly" 33 | day: "friday" 34 | open-pull-requests-limit: 4 35 | groups: 36 | development-dependencies: 37 | patterns: 38 | - "github.com/stretchr/testify" 39 | 40 | golang-org-dependencies: 41 | patterns: 42 | - "golang.org/*" 43 | 44 | go-openapi-dependencies: 45 | patterns: 46 | - "github.com/go-openapi/*" 47 | 48 | other-dependencies: 49 | exclude-patterns: 50 | - "github.com/go-openapi/*" 51 | - "github.com/stretchr/testify" 52 | - "golang.org/*" 53 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/anyOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "anyOf", 4 | "schema": { 5 | "anyOf": [ 6 | { 7 | "type": "integer" 8 | }, 9 | { 10 | "minimum": 2 11 | } 12 | ] 13 | }, 14 | "tests": [ 15 | { 16 | "description": "first anyOf valid", 17 | "data": 1, 18 | "valid": true 19 | }, 20 | { 21 | "description": "second anyOf valid", 22 | "data": 2.5, 23 | "valid": true 24 | }, 25 | { 26 | "description": "both anyOf valid", 27 | "data": 3, 28 | "valid": true 29 | }, 30 | { 31 | "description": "neither anyOf valid", 32 | "data": 1.5, 33 | "valid": false 34 | } 35 | ] 36 | }, 37 | { 38 | "description": "anyOf with base schema", 39 | "schema": { 40 | "type": "string", 41 | "anyOf" : [ 42 | { 43 | "maxLength": 2 44 | }, 45 | { 46 | "minLength": 4 47 | } 48 | ] 49 | }, 50 | "tests": [ 51 | { 52 | "description": "mismatch base schema", 53 | "data": 3, 54 | "valid": false 55 | }, 56 | { 57 | "description": "one anyOf valid", 58 | "data": "foobar", 59 | "valid": true 60 | }, 61 | { 62 | "description": "both anyOf invalid", 63 | "data": "foo", 64 | "valid": false 65 | } 66 | ] 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/oneOf.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "oneOf", 4 | "schema": { 5 | "oneOf": [ 6 | { 7 | "type": "integer" 8 | }, 9 | { 10 | "minimum": 2 11 | } 12 | ] 13 | }, 14 | "tests": [ 15 | { 16 | "description": "first oneOf valid", 17 | "data": 1, 18 | "valid": true 19 | }, 20 | { 21 | "description": "second oneOf valid", 22 | "data": 2.5, 23 | "valid": true 24 | }, 25 | { 26 | "description": "both oneOf valid", 27 | "data": 3, 28 | "valid": false 29 | }, 30 | { 31 | "description": "neither oneOf valid", 32 | "data": 1.5, 33 | "valid": false 34 | } 35 | ] 36 | }, 37 | { 38 | "description": "oneOf with base schema", 39 | "schema": { 40 | "type": "string", 41 | "oneOf" : [ 42 | { 43 | "minLength": 2 44 | }, 45 | { 46 | "maxLength": 4 47 | } 48 | ] 49 | }, 50 | "tests": [ 51 | { 52 | "description": "mismatch base schema", 53 | "data": 3, 54 | "valid": false 55 | }, 56 | { 57 | "description": "one oneOf valid", 58 | "data": "foobar", 59 | "valid": true 60 | }, 61 | { 62 | "description": "both oneOf valid", 63 | "data": "foo", 64 | "valid": false 65 | } 66 | ] 67 | } 68 | ] 69 | -------------------------------------------------------------------------------- /formats_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "fmt" 8 | "reflect" 9 | "testing" 10 | 11 | "github.com/go-openapi/spec" 12 | "github.com/go-openapi/strfmt" 13 | "github.com/go-openapi/testify/v2/assert" 14 | ) 15 | 16 | // Validator for string formats 17 | func TestFormatValidator_EdgeCases(t *testing.T) { 18 | // Apply 19 | v := newFormatValidator( 20 | "", "", "", strfmt.Default, nil, 21 | ) 22 | v.SetPath("a.b.c") 23 | 24 | // formatValidator applies to: Items, Parameter,Schema 25 | 26 | p := spec.Parameter{} 27 | p.Typed(stringType, "email") 28 | s := spec.Schema{} 29 | s.Typed(stringType, "uuid") 30 | i := spec.Items{} 31 | i.Typed(stringType, "datetime") 32 | 33 | sources := []any{&p, &s, &i} 34 | 35 | for _, source := range sources { 36 | // Default formats for strings 37 | assert.True(t, v.Applies(source, reflect.String)) 38 | // Do not apply for number formats 39 | assert.False(t, v.Applies(source, reflect.Int)) 40 | } 41 | 42 | assert.False(t, v.Applies("A string", reflect.String)) 43 | assert.False(t, v.Applies(nil, reflect.String)) 44 | } 45 | 46 | func TestStringValidation(t *testing.T) { 47 | type testParams struct { 48 | format string 49 | obj fmt.Stringer 50 | } 51 | 52 | testCases := []*testParams{ 53 | { 54 | format: "datetime", 55 | obj: strfmt.NewDateTime(), 56 | }, 57 | { 58 | format: "uuid", 59 | obj: strfmt.UUID("00000000-0000-0000-0000-000000000000"), 60 | }, 61 | { 62 | format: "email", 63 | obj: strfmt.Email("name@domain.tld"), 64 | }, 65 | { 66 | format: "bsonobjectid", 67 | obj: strfmt.NewObjectId("60a7903427a1e6666d2b998c"), 68 | }, 69 | } 70 | 71 | for _, v := range testCases { 72 | err := FormatOf(testID, "body", v.format, v.obj.String(), strfmt.Default) 73 | assert.Nil(t, err) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /fixtures/go-swagger/bugs/163/swagger.yml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | version: '2' 4 | title: Server Rest API 5 | 6 | basePath: /rest/api/2/ 7 | schemes: 8 | - https 9 | consumes: 10 | - application/json 11 | produces: 12 | - application/json 13 | paths: 14 | '/search': 15 | get: 16 | operationId: getSearch 17 | # Per docs: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#parameterObject 18 | # Required. The type of the parameter. Since the parameter is not located at the request body, it is limited to simple types (that is, not an object). The value MUST be one of "string", "number", "integer", "boolean", "array" or "file". 19 | parameters: 20 | - name: stringTypeInQuery 21 | type: string 22 | in: query 23 | default: "qsValue" 24 | - name: numberTypeInQuery 25 | type: number 26 | in: query 27 | - name: integerTypeInQuery 28 | type: integer 29 | in: query 30 | - name: booleanTypeInQuery 31 | type: boolean 32 | in: query 33 | 34 | - name: stringArrayTypeInQuery 35 | type: array 36 | items: 37 | type: string 38 | in: query 39 | - name: numberArrayTypeInQuery 40 | type: array 41 | items: 42 | type: string 43 | in: query 44 | - name: integerArrayTypeInQuery 45 | type: array 46 | items: 47 | type: string 48 | in: query 49 | - name: booleanArrayTypeInQuery 50 | type: array 51 | items: 52 | type: string 53 | in: query 54 | 55 | responses: 56 | '200': 57 | description: Success 58 | schema: 59 | $ref: '#/definitions/SearchResponse' 60 | 61 | 62 | 63 | definitions: 64 | SearchResponse: 65 | type: object 66 | properties: 67 | message: 68 | type: string 69 | -------------------------------------------------------------------------------- /options.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import "sync" 7 | 8 | // Opts specifies validation options for a SpecValidator. 9 | // 10 | // NOTE: other options might be needed, for example a go-swagger specific mode. 11 | type Opts struct { 12 | ContinueOnErrors bool // true: continue reporting errors, even if spec is invalid 13 | 14 | // StrictPathParamUniqueness enables a strict validation of paths that include 15 | // path parameters. When true, it will enforce that for each method, the path 16 | // is unique, regardless of path parameters such that GET:/petstore/{id} and 17 | // GET:/petstore/{pet} anre considered duplicate paths. 18 | // 19 | // Consider disabling if path parameters can include slashes such as 20 | // GET:/v1/{shelve} and GET:/v1/{book}, where the IDs are "shelve/*" and 21 | // /"shelve/*/book/*" respectively. 22 | StrictPathParamUniqueness bool 23 | SkipSchemataResult bool 24 | } 25 | 26 | var ( 27 | defaultOpts = Opts{ 28 | // default is to stop validation on errors 29 | ContinueOnErrors: false, 30 | 31 | // StrictPathParamUniqueness is defaulted to true. This maintains existing 32 | // behavior. 33 | StrictPathParamUniqueness: true, 34 | } 35 | 36 | defaultOptsMutex = &sync.Mutex{} 37 | ) 38 | 39 | // SetContinueOnErrors sets global default behavior regarding spec validation errors reporting. 40 | // 41 | // For extended error reporting, you most likely want to set it to true. 42 | // For faster validation, it's better to give up early when a spec is detected as invalid: set it to false (this is the default). 43 | // 44 | // Setting this mode does NOT affect the validation status. 45 | // 46 | // NOTE: this method affects global defaults. It is not suitable for a concurrent usage. 47 | func SetContinueOnErrors(c bool) { 48 | defer defaultOptsMutex.Unlock() 49 | defaultOptsMutex.Lock() 50 | defaultOpts.ContinueOnErrors = c 51 | } 52 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-43-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "title": "Test", 5 | "description": "Tests issue with examples and nested objects with items properties", 6 | "version": "1.0" 7 | }, 8 | "host": "FooBar", 9 | "basePath": "/latest", 10 | "schemes": [ 11 | "https" 12 | ], 13 | "produces": [ 14 | "application/json" 15 | ], 16 | "paths": { 17 | "/foo/": { 18 | "get": { 19 | "description": "Tests issue with nested items object properties and examples", 20 | "summary": "Tests issue with nested items object properties and examples", 21 | "responses": { 22 | "200": { 23 | "description": "Example should match spec", 24 | "schema": { 25 | "type": "array", 26 | "items": { 27 | "type": "object", 28 | "properties": { 29 | "items": { 30 | "type": "array", 31 | "maxItems": 255, 32 | "items": { 33 | "type": "object", 34 | "properties": { 35 | "id": { 36 | "type": "integer", 37 | "format": "int32" 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /fixtures/bugs/43/fixture-43-variants.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Object 4 | version: 0.1.0 5 | 6 | paths: 7 | /: 8 | get: 9 | parameters: 10 | - name: itemsparam 11 | in: body 12 | schema: 13 | type: array 14 | items: 15 | type: object 16 | required: [ items ] 17 | properties: 18 | items: 19 | type: number 20 | example: 21 | - items: 123 22 | - items: 456 23 | responses: 24 | '200': 25 | description: Ok 26 | schema: 27 | type: object 28 | properties: 29 | a: 30 | type: string 31 | items: 32 | type: string 33 | default: "xyz" 34 | example: "123" 35 | examples: 36 | application/json: 37 | a: abc 38 | items: xyz 39 | # we verify that it is legal to name a property "type" or "properties" 40 | /type: 41 | get: 42 | parameters: 43 | - name: typeparam 44 | in: body 45 | schema: 46 | type: object 47 | properties: 48 | type: 49 | type: string 50 | example: z 51 | properties: 52 | type: number 53 | example: 1 54 | default: { "type": "abc", "properties": 123 } 55 | example: { "type": "abc", "properties": 123 } 56 | responses: 57 | '200': 58 | description: Ok 59 | schema: 60 | type: object 61 | properties: 62 | type: 63 | type: string 64 | properties: 65 | type: number 66 | default: 123 67 | example: 123 68 | examples: 69 | application/json: 70 | type: abc 71 | properties: 123 72 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-342.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: issue-342 4 | description: | 5 | Original issue: a spec which triggers a panic because of invalid type assertion on parameters. 6 | Specifically, this tests how validation carries on when references returns an unexpected object. 7 | This may happen for parameters and responses and should be accurately reported. 8 | version: 0.0.1 9 | license: 10 | name: MIT 11 | host: localhost:8081 12 | basePath: /api/v1 13 | schemes: 14 | - http 15 | consumes: 16 | - application/json 17 | produces: 18 | - application/json 19 | paths: 20 | /get_main_object: 21 | get: 22 | tags: 23 | - maindata 24 | parameters: 25 | - name: pquery1 26 | in: query 27 | required: true 28 | $ref: "#/definitions/sample_info/properties/sid" # <-- error: a whole schema replaces the parameter 29 | - $ref: "#/parameters/wrong" # <-- error: wrong param props 30 | - $ref: "#/parameters/notbetter" # <-- error: wrong param schema 31 | - $ref: "#/parameters/stillnogood" # <-- error: wrong param schema 32 | - name: pquery2 33 | in: query 34 | required: true 35 | $ref: "nowhere.yaml#/definitions/sample_info/properties/sid" # <-- error: expand ref error 36 | - name: sid 37 | in: body 38 | required: true 39 | $ref: "#/definitions/sample_info/properties/sid" # <-- error: a whole schema replaces the parameter 40 | responses: 41 | '200': 42 | 43 | parameters: 44 | wrong: 45 | theName: wrongNameProperty 46 | theType: wrongTypePropery 47 | notbetter: 48 | type: object 49 | properties: 50 | whenDidThatHappen: 51 | type: string 52 | format: date 53 | stillnogood: 54 | schema: 55 | type: object 56 | properties: 57 | aintnogood: 58 | type: integer 59 | definitions: 60 | sample_info: 61 | type: object 62 | properties: 63 | sid: 64 | type: string 65 | format: uuid 66 | 67 | -------------------------------------------------------------------------------- /fixtures/go-swagger/expansion/invalid-refs.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Swagger Petstore", 6 | "contact": { 7 | "name": "wordnik api team", 8 | "url": "http://developer.wordnik.com" 9 | }, 10 | "license": { 11 | "name": "Creative Commons 4.0 International", 12 | "url": "http://creativecommons.org/licenses/by/4.0/" 13 | } 14 | }, 15 | "host": "petstore.swagger.wordnik.com", 16 | "basePath": "/api", 17 | "schemes": [ 18 | "http" 19 | ], 20 | "paths": { 21 | "/pets": { 22 | "get": { 23 | "tags": [ "Pet Operations" ], 24 | "summary": "finds pets in the system", 25 | "responses": { 26 | "200": { 27 | "description": "pet response", 28 | "schema": { 29 | "type": "array", 30 | "items": { 31 | "$ref": "NotCorrectRef" 32 | } 33 | }, 34 | "headers": { 35 | "x-expires": { 36 | "type": "string" 37 | } 38 | } 39 | }, 40 | "default": { 41 | "description": "unexpected error", 42 | "schema": { 43 | "$ref": "NotCorrectRef" 44 | } 45 | } 46 | } 47 | } 48 | } 49 | }, 50 | "definitions": { 51 | "Pet": { 52 | "required": [ 53 | "id", 54 | "name" 55 | ], 56 | "properties": { 57 | "id": { 58 | "type": "integer", 59 | "format": "int64" 60 | }, 61 | "name": { 62 | "type": "string" 63 | }, 64 | "tag": { 65 | "type": "string" 66 | } 67 | } 68 | }, 69 | "Error": { 70 | "required": [ 71 | "code", 72 | "message" 73 | ], 74 | "properties": { 75 | "code": { 76 | "type": "integer", 77 | "format": "int32" 78 | }, 79 | "message": { 80 | "type": "string" 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /fixtures/go-swagger/petstores/petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "version": "1.0.0", 5 | "title": "Swagger Petstore", 6 | "contact": { 7 | "name": "wordnik api team", 8 | "url": "http://developer.wordnik.com" 9 | }, 10 | "license": { 11 | "name": "Creative Commons 4.0 International", 12 | "url": "http://creativecommons.org/licenses/by/4.0/" 13 | } 14 | }, 15 | "host": "petstore.swagger.wordnik.com", 16 | "basePath": "/api", 17 | "schemes": [ 18 | "http" 19 | ], 20 | "paths": { 21 | "/pets": { 22 | "get": { 23 | "tags": [ "Pet Operations" ], 24 | "summary": "finds pets in the system", 25 | "responses": { 26 | "200": { 27 | "description": "pet response", 28 | "schema": { 29 | "type": "array", 30 | "items": { 31 | "$ref": "#/definitions/Pet" 32 | } 33 | }, 34 | "headers": { 35 | "x-expires": { 36 | "type": "string" 37 | } 38 | } 39 | }, 40 | "default": { 41 | "description": "unexpected error", 42 | "schema": { 43 | "$ref": "#/definitions/Error" 44 | } 45 | } 46 | } 47 | } 48 | } 49 | }, 50 | "definitions": { 51 | "Pet": { 52 | "required": [ 53 | "id", 54 | "name" 55 | ], 56 | "properties": { 57 | "id": { 58 | "type": "integer", 59 | "format": "int64" 60 | }, 61 | "name": { 62 | "type": "string" 63 | }, 64 | "tag": { 65 | "type": "string" 66 | } 67 | } 68 | }, 69 | "Error": { 70 | "required": [ 71 | "code", 72 | "message" 73 | ], 74 | "properties": { 75 | "code": { 76 | "type": "integer", 77 | "format": "int32" 78 | }, 79 | "message": { 80 | "type": "string" 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /helpers_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "errors" 8 | "testing" 9 | 10 | "github.com/go-openapi/testify/v2/assert" 11 | "github.com/go-openapi/testify/v2/require" 12 | ) 13 | 14 | var errMyError = errors.New("my error") 15 | 16 | func TestHelpers_addPointerError(t *testing.T) { 17 | res := new(Result) 18 | r := errorHelp.addPointerError(res, errMyError, "my ref", "path") 19 | require.NotEmpty(t, r.Errors) 20 | msg := r.Errors[0].Error() 21 | assert.Contains(t, msg, "could not resolve reference in path to $ref my ref: my error") 22 | } 23 | 24 | //nolint:gosec 25 | func integerFactory(base int) []any { 26 | return []any{ 27 | base, 28 | int8(base), 29 | int16(base), 30 | int32(base), 31 | int64(base), 32 | uint(base), 33 | uint8(base), 34 | uint16(base), 35 | uint32(base), 36 | uint64(base), 37 | float32(base), 38 | float64(base), 39 | } 40 | } 41 | 42 | // Test cases in private method asInt64() 43 | func TestHelpers_asInt64(t *testing.T) { 44 | for _, v := range integerFactory(3) { 45 | assert.Equal(t, int64(3), valueHelp.asInt64(v)) 46 | } 47 | 48 | // Non numeric 49 | if assert.NotPanics(t, func() { 50 | valueHelp.asInt64("123") 51 | }) { 52 | assert.Equal(t, int64(0), valueHelp.asInt64("123")) 53 | } 54 | } 55 | 56 | // Test cases in private method asUint64() 57 | func TestHelpers_asUint64(t *testing.T) { 58 | for _, v := range integerFactory(3) { 59 | assert.Equal(t, uint64(3), valueHelp.asUint64(v)) 60 | } 61 | 62 | // Non numeric 63 | if assert.NotPanics(t, func() { 64 | valueHelp.asUint64("123") 65 | }) { 66 | assert.Equal(t, uint64(0), valueHelp.asUint64("123")) 67 | } 68 | } 69 | 70 | // Test cases in private method asFloat64() 71 | func TestHelpers_asFloat64(t *testing.T) { 72 | const epsilon = 1e-9 73 | 74 | for _, v := range integerFactory(3) { 75 | assert.InDelta(t, float64(3), valueHelp.asFloat64(v), epsilon) 76 | } 77 | 78 | // Non numeric 79 | if assert.NotPanics(t, func() { 80 | valueHelp.asFloat64("123") 81 | }) { 82 | assert.InDelta(t, float64(0), valueHelp.asFloat64("123"), epsilon) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/refRemote.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "remote ref", 4 | "schema": {"$ref": "http://localhost:1234/integer.json"}, 5 | "tests": [ 6 | { 7 | "description": "remote ref valid", 8 | "data": 1, 9 | "valid": true 10 | }, 11 | { 12 | "description": "remote ref invalid", 13 | "data": "a", 14 | "valid": false 15 | } 16 | ] 17 | }, 18 | { 19 | "description": "fragment within remote ref", 20 | "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, 21 | "tests": [ 22 | { 23 | "description": "remote fragment valid", 24 | "data": 1, 25 | "valid": true 26 | }, 27 | { 28 | "description": "remote fragment invalid", 29 | "data": "a", 30 | "valid": false 31 | } 32 | ] 33 | }, 34 | { 35 | "description": "ref within remote ref", 36 | "schema": { 37 | "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" 38 | }, 39 | "tests": [ 40 | { 41 | "description": "ref within ref valid", 42 | "data": 1, 43 | "valid": true 44 | }, 45 | { 46 | "description": "ref within ref invalid", 47 | "data": "a", 48 | "valid": false 49 | } 50 | ] 51 | }, 52 | { 53 | "description": "base URI change", 54 | "schema": { 55 | "id": "http://localhost:1234/", 56 | "items": { 57 | "id": "folder/", 58 | "items": {"$ref": "folderInteger.json"} 59 | } 60 | }, 61 | "tests": [ 62 | { 63 | "description": "base URI change ref valid", 64 | "data": [[1]], 65 | "valid": true 66 | }, 67 | { 68 | "description": "base URI change ref invalid", 69 | "data": [["a"]], 70 | "valid": false 71 | } 72 | ] 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /fixtures/jsonschema_suite/enum.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "description": "simple enum validation", 4 | "schema": {"enum": [1, 2, 3]}, 5 | "tests": [ 6 | { 7 | "description": "one of the enum is valid", 8 | "data": 1, 9 | "valid": true 10 | }, 11 | { 12 | "description": "something else is invalid", 13 | "data": 4, 14 | "valid": false 15 | } 16 | ] 17 | }, 18 | { 19 | "description": "heterogeneous enum validation", 20 | "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, 21 | "tests": [ 22 | { 23 | "description": "one of the enum is valid", 24 | "data": [], 25 | "valid": true 26 | }, 27 | { 28 | "description": "something else is invalid", 29 | "data": null, 30 | "valid": false 31 | }, 32 | { 33 | "description": "objects are deep compared", 34 | "data": {"foo": false}, 35 | "valid": false 36 | } 37 | ] 38 | }, 39 | { 40 | "description": "enums in properties", 41 | "schema": { 42 | "type":"object", 43 | "properties": { 44 | "foo": {"enum":["foo"]}, 45 | "bar": {"enum":["bar"]} 46 | }, 47 | "required": ["bar"] 48 | }, 49 | "tests": [ 50 | { 51 | "description": "both properties are valid", 52 | "data": {"foo":"foo", "bar":"bar"}, 53 | "valid": true 54 | }, 55 | { 56 | "description": "missing optional property is valid", 57 | "data": {"bar":"bar"}, 58 | "valid": true 59 | }, 60 | { 61 | "description": "missing required property is invalid", 62 | "data": {"foo":"foo"}, 63 | "valid": false 64 | }, 65 | { 66 | "description": "missing all properties is invalid", 67 | "data": {}, 68 | "valid": false 69 | } 70 | ] 71 | } 72 | ] 73 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-581-good-numbers.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: 'fixture for issue #581' 5 | version: '1.0' 6 | description: | 7 | This one just to set a minimum/maximum valid case for non regression. 8 | It exersises, for numbers: 9 | - inline parameters 10 | - schema parameters 11 | - schema parameters through $ref 12 | - schema for response 13 | - schema object for response, with object and array 14 | - schema for response through $ref 15 | 16 | 17 | produces: 18 | - application/json 19 | paths: 20 | /fixture: 21 | get: 22 | operationId: op1 23 | parameters: 24 | - name: myid 25 | in: body 26 | schema: 27 | $ref: '#/definitions/myId' 28 | responses: 29 | 200: 30 | description: 'response exercising number boundaries' 31 | schema: 32 | $ref: '#/definitions/someIds' 33 | 201: 34 | description: 'response exercising number boundaries' 35 | schema: 36 | type: number 37 | minimum: 0 38 | maximum: 100 39 | default: 0 40 | 401: 41 | description: 'response exercising number boundaries' 42 | schema: 43 | type: object 44 | properties: 45 | shortInt: 46 | type: number 47 | minimum: 0 48 | maximum: 100 49 | default: 0 50 | shortIntList: 51 | type: array 52 | items: 53 | type: number 54 | minimum: 0 55 | maximum: 100 56 | default: 0 57 | 58 | definitions: 59 | myId: 60 | type: object 61 | properties: 62 | smallId: 63 | type: number 64 | minimum: 0 65 | maximum: 12 66 | default: 10 67 | format: uint64 68 | someIds: 69 | type: object 70 | properties: 71 | smallId: 72 | type: number 73 | minimum: 0 74 | maximum: 12 75 | default: 10 76 | format: uint64 77 | smallIdList: 78 | type: array 79 | items: 80 | type: number 81 | minimum: 0 82 | maximum: 100 83 | default: 0 84 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-581-good.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | swagger: '2.0' 3 | info: 4 | title: 'fixture for issue #581' 5 | version: '1.0' 6 | description: | 7 | This one just to set a minimum/maximum valid case for non regression. 8 | It exersises, for integers: 9 | - inline parameters 10 | - schema parameters 11 | - schema parameters through $ref 12 | - schema for response 13 | - schema object for response, with object and array 14 | - schema for response through $ref 15 | 16 | 17 | produces: 18 | - application/json 19 | paths: 20 | /fixture: 21 | get: 22 | operationId: op1 23 | parameters: 24 | - name: myid 25 | in: body 26 | schema: 27 | $ref: '#/definitions/myId' 28 | responses: 29 | 200: 30 | description: 'response exercising integer boundaries' 31 | schema: 32 | $ref: '#/definitions/someIds' 33 | 201: 34 | description: 'response exercising integer boundaries' 35 | schema: 36 | type: integer 37 | minimum: 0 38 | maximum: 100 39 | default: 0 40 | 401: 41 | description: 'response exercising integer boundaries' 42 | schema: 43 | type: object 44 | properties: 45 | shortInt: 46 | type: integer 47 | minimum: 0 48 | maximum: 100 49 | default: 0 50 | shortIntList: 51 | type: array 52 | items: 53 | type: integer 54 | minimum: 0 55 | maximum: 100 56 | default: 0 57 | 58 | definitions: 59 | myId: 60 | type: object 61 | properties: 62 | smallId: 63 | type: integer 64 | minimum: 0 65 | maximum: 12 66 | default: 10 67 | format: uint64 68 | someIds: 69 | type: object 70 | properties: 71 | smallId: 72 | type: integer 73 | minimum: 0 74 | maximum: 12 75 | default: 10 76 | format: uint64 77 | smallIdList: 78 | type: array 79 | items: 80 | type: integer 81 | minimum: 0 82 | maximum: 100 83 | default: 0 84 | -------------------------------------------------------------------------------- /formats.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package validate 5 | 6 | import ( 7 | "reflect" 8 | 9 | "github.com/go-openapi/spec" 10 | "github.com/go-openapi/strfmt" 11 | ) 12 | 13 | type formatValidator struct { 14 | Path string 15 | In string 16 | Format string 17 | KnownFormats strfmt.Registry 18 | Options *SchemaValidatorOptions 19 | } 20 | 21 | func newFormatValidator(path, in, format string, formats strfmt.Registry, opts *SchemaValidatorOptions) *formatValidator { 22 | if opts == nil { 23 | opts = new(SchemaValidatorOptions) 24 | } 25 | 26 | var f *formatValidator 27 | if opts.recycleValidators { 28 | f = pools.poolOfFormatValidators.BorrowValidator() 29 | } else { 30 | f = new(formatValidator) 31 | } 32 | 33 | f.Path = path 34 | f.In = in 35 | f.Format = format 36 | f.KnownFormats = formats 37 | f.Options = opts 38 | 39 | return f 40 | } 41 | 42 | func (f *formatValidator) SetPath(path string) { 43 | f.Path = path 44 | } 45 | 46 | func (f *formatValidator) Applies(source any, kind reflect.Kind) bool { 47 | if source == nil || f.KnownFormats == nil { 48 | return false 49 | } 50 | 51 | switch source := source.(type) { 52 | case *spec.Items: 53 | return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) 54 | case *spec.Parameter: 55 | return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) 56 | case *spec.Schema: 57 | return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) 58 | case *spec.Header: 59 | return kind == reflect.String && f.KnownFormats.ContainsName(source.Format) 60 | default: 61 | return false 62 | } 63 | } 64 | 65 | func (f *formatValidator) Validate(val any) *Result { 66 | if f.Options.recycleValidators { 67 | defer func() { 68 | f.redeem() 69 | }() 70 | } 71 | 72 | var result *Result 73 | if f.Options.recycleResult { 74 | result = pools.poolOfResults.BorrowResult() 75 | } else { 76 | result = new(Result) 77 | } 78 | 79 | if err := FormatOf(f.Path, f.In, f.Format, val.(string), f.KnownFormats); err != nil { 80 | result.AddErrors(err) 81 | } 82 | 83 | return result 84 | } 85 | 86 | func (f *formatValidator) redeem() { 87 | pools.poolOfFormatValidators.RedeemValidator(f) 88 | } 89 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-161-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "", 5 | "version": "1.0.0", 6 | "title": "issue#161", 7 | "termsOfService": "http://helloreverb.com/terms/", 8 | "contact": { 9 | "name": "apiteam@wordnik.com" 10 | }, 11 | "license": { 12 | "name": "Apache 2.0", 13 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 14 | } 15 | }, 16 | "host": "petstore.swagger.wordnik.com", 17 | "basePath": "/v2", 18 | "schemes": [ 19 | "http" 20 | ], 21 | "paths": { 22 | "/folders": { 23 | "post": { 24 | "parameters": [{ 25 | "name": "requestBody", 26 | "in": "body", 27 | "description": "body parameter", 28 | "required": true, 29 | "schema": { 30 | "type": "object", 31 | "title": "body of creating folder", 32 | "description": "body parameter of creating folder", 33 | "default": "{\"name\":\"new\",\"parent\":{\"id\":\"0\"}}", 34 | "required": ["name", "parent"], 35 | "properties": { 36 | "name": { 37 | "type": "string" 38 | }, 39 | "parent": { 40 | "type": "object", 41 | "properties": { 42 | "id": { 43 | "type": "number" 44 | } 45 | } 46 | } 47 | }, 48 | "readOnly": false, 49 | "externalDocs": { 50 | "description": "create a new folder.", 51 | "url": "https://box-content.readme.io/#create-a-new-folder" 52 | }, 53 | "example": { 54 | "name": "newname.jpg", 55 | "parent": { 56 | "id": "0" 57 | } 58 | } 59 | } 60 | }], 61 | "responses": { 62 | "200": { 63 | "description": "Some response" 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-161.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "", 5 | "version": "1.0.0", 6 | "title": "issue#161", 7 | "termsOfService": "http://helloreverb.com/terms/", 8 | "contact": { 9 | "name": "apiteam@wordnik.com" 10 | }, 11 | "license": { 12 | "name": "Apache 2.0", 13 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 14 | } 15 | }, 16 | "host": "petstore.swagger.wordnik.com", 17 | "basePath": "/v2", 18 | "schemes": [ 19 | "http" 20 | ], 21 | "paths": { 22 | "/folders": { 23 | "post": { 24 | "parameters": [{ 25 | "name": "requestBody", 26 | "in": "body", 27 | "description": "body parameter", 28 | "required": true, 29 | "schema": { 30 | "type": "object", 31 | "title": "body of creating folder", 32 | "description": "body parameter of creating folder", 33 | "default": "{\"name\":\"new\",\"parent\":{\"id\":\"0\"}}", 34 | "required": ["name", "parent"], 35 | "properties": { 36 | "name": { 37 | "type": "object" 38 | }, 39 | "parent": { 40 | "type": "object", 41 | "properties": { 42 | "id": { 43 | "type": "number" 44 | } 45 | } 46 | } 47 | }, 48 | "readOnly": false, 49 | "externalDocs": { 50 | "description": "create a new folder.", 51 | "url": "https://box-content.readme.io/#create-a-new-folder" 52 | }, 53 | "example": { 54 | "name": "newname.jpg", 55 | "parent": { 56 | "id": "0" 57 | } 58 | } 59 | } 60 | }], 61 | "responses": { 62 | "200": { 63 | "description": "Some response" 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /fixtures/pruning/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "foo": { 4 | "type": "integer" 5 | }, 6 | "bar": { 7 | "type": "integer" 8 | }, 9 | "nested": { 10 | "type": "object", 11 | "properties": { 12 | "inner": { 13 | "type": "object", 14 | "properties": { 15 | "foo": { 16 | "type": "integer" 17 | }, 18 | "bar": { 19 | "type": "integer" 20 | } 21 | } 22 | } 23 | } 24 | }, 25 | "all": { 26 | "allOf": [ 27 | { 28 | "type": "object", 29 | "properties": { 30 | "foo": { 31 | "type": "integer" 32 | } 33 | } 34 | }, 35 | { 36 | "type": "object", 37 | "properties": { 38 | "bar": { 39 | "type": "integer" 40 | } 41 | } 42 | } 43 | ] 44 | }, 45 | "any": { 46 | "anyOf": [ 47 | { 48 | "type": "object", 49 | "properties": { 50 | "foo": { 51 | "type": "integer" 52 | } 53 | } 54 | }, 55 | { 56 | "type": "object", 57 | "properties": { 58 | "bar": { 59 | "type": "integer" 60 | } 61 | } 62 | } 63 | ] 64 | }, 65 | "one": { 66 | "oneOf": [ 67 | { 68 | "type": "object", 69 | "properties": { 70 | "foo": { 71 | "type": "integer" 72 | } 73 | }, 74 | "required": ["foo"] 75 | }, 76 | { 77 | "type": "object", 78 | "properties": { 79 | "bar": { 80 | "type": "integer" 81 | } 82 | } 83 | } 84 | ] 85 | }, 86 | "not": { 87 | "not": { 88 | "type": "object", 89 | "properties": { 90 | "foo": { 91 | "type": "integer" 92 | } 93 | } 94 | } 95 | }, 96 | "array": { 97 | "items": { 98 | "properties": { 99 | "foo": {} 100 | } 101 | } 102 | } 103 | }, 104 | "required": ["foo", "bar", "nested", "all", "any", "one"] 105 | } 106 | -------------------------------------------------------------------------------- /fixtures/validation/fixture-161-good.json: -------------------------------------------------------------------------------- 1 | { 2 | "swagger": "2.0", 3 | "info": { 4 | "description": "", 5 | "version": "1.0.0", 6 | "title": "issue#161", 7 | "termsOfService": "http://helloreverb.com/terms/", 8 | "contact": { 9 | "name": "apiteam@wordnik.com" 10 | }, 11 | "license": { 12 | "name": "Apache 2.0", 13 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 14 | } 15 | }, 16 | "host": "petstore.swagger.wordnik.com", 17 | "basePath": "/v2", 18 | "schemes": [ 19 | "http" 20 | ], 21 | "paths": { 22 | "/folders": { 23 | "post": { 24 | "parameters": [{ 25 | "name": "requestBody", 26 | "in": "body", 27 | "description": "body parameter", 28 | "required": true, 29 | "schema": { 30 | "type": "object", 31 | "title": "body of creating folder", 32 | "description": "body parameter of creating folder", 33 | "default": { 34 | "name": "new", 35 | "parent":{ 36 | "id": 0 37 | } 38 | }, 39 | "required": ["name", "parent"], 40 | "properties": { 41 | "name": { 42 | "type": "string" 43 | }, 44 | "parent": { 45 | "type": "object", 46 | "properties": { 47 | "id": { 48 | "type": "number" 49 | } 50 | } 51 | } 52 | }, 53 | "readOnly": false, 54 | "externalDocs": { 55 | "description": "create a new folder.", 56 | "url": "https://box-content.readme.io/#create-a-new-folder" 57 | }, 58 | "example": { 59 | "name": "newname.jpg", 60 | "parent": { 61 | "id": "0" 62 | } 63 | } 64 | } 65 | }], 66 | "responses": { 67 | "200": { 68 | "description": "Some response" 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | --------------------------------------------------------------------------------