Skip to content
This repository has been archived by the owner on Aug 4, 2023. It is now read-only.

Swagger with extensions fails to validate #597

Open
alasdairhurst opened this issue Feb 1, 2019 · 1 comment
Open

Swagger with extensions fails to validate #597

alasdairhurst opened this issue Feb 1, 2019 · 1 comment

Comments

@alasdairhurst
Copy link

Given the following swagger file (valid), swagger tools fails to validate it.
Error: cannot read property properties of null

It is assuming that all keys under "paths" are paths and not checking for extensions which may be there. There may be other issues too.

{
	"swagger": "2.0",
	"x-an-extension-null": null,
	"x-an-extension-primitive": 1,
	"x-an-extension-array": [],
	"x-an-extension-object": {},
	"host": "localhost:8080",
	"basePath": "/test",
	"schemes": [
		"http",
		"https",
		"ws",
		"wss"
	],
	"consumes": [
		"application/json"
	],
	"produces": [
		"application/json"
	],
	"info": {
		"version": "0.0.0",
		"title": "Thing API",
		"contact": {
			"name": "Person",
			"url": "http://www.person.com",
			"email": "[email protected]",
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {}
		},
		"license": {
			"name": "FREE",
			"url": "http://www.person.com",
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {}
		},
		"x-an-extension-null": null,
		"x-an-extension-primitive": 1,
		"x-an-extension-array": [],
		"x-an-extension-object": {}
	},
	"parameters": {
		"apiKey": {
			"in": "query",
			"name": "apiKey",
			"type": "string",
			"required": true
		},
		"name": {
			"name": "name",
			"enum": [
				"foo",
				"bar",
				"baz"
			],
			"in": "query",
			"type": "string",
			"format": "password",
			"allowEmptyValue": true
		},
		"fooArr": {
			"name": "fooArr",
			"in": "query",
			"type": "array",
			"description": "an array of array of strings no bigger than 10 characters beginning with h y or m",
			"collectionFormat": "pipes",
			"uniqueItems": true,
			"default": [
				[
					"hello",
					"you"
				],
				[
					"me"
				]
			],
			"items": {
				"type": "array",
				"collectionFormat": "csv",
				"default": [
					"hello",
					"me"
				],
				"items": {
					"type": "string",
					"maxLength": 10,
					"minLength": 2,
					"pattern": "^[hmy]"
				}
			}
		},
		"barInt": {
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {},
			"in": "query",
			"description": "an integer which is a multiple of 5 but bigger than 5 and no bigger than 100",
			"name": "barInt",
			"type": "integer",
			"multipleOf": 5,
			"maximum": 100,
			"exclusiveMaximum": false,
			"minimum": 5,
			"exclusiveMinimum": true
		}
	},
	"paths": {
		"x-an-extension-null": null,
		"x-an-extension-primitive": 1,
		"x-an-extension-array": [],
		"x-an-extension-object": {
			"get": {
				"description": "this is an x- extension and not a path/method",
				"responses": {
					"default": {
						"description": "too lazy to make a 200"
					}
				}
			}
		},
		"x-not-a-path-but-used-in-ref": {
			"get": {
				"description": "this is a method used by a path which isn't 'x-not-a-path-but-used-in-ref'",
				"responses": {
					"default": {
						"description": "too lazy to make a 200"
					}
				}
			}
		},
		"/thingEmpty": {},
		"/thingyref": {
			"$ref": "#/paths/x-not-a-path-but-used-in-ref"
		},
		"/thing": {
			"parameters": [
				{
					"$ref": "#/parameters/apiKey"
				}
			],
			"get": {
				"x-an-extension-null": null,
				"x-an-extension-primitive": 1,
				"x-an-extension-array": [],
				"x-an-extension-object": {},
				"description": "has no operation id, no parameters",
				"responses": {
					"default": {
						"description": "too lazy to make a 200"
					}
				}
			},
			"patch": {
				"x-an-extension-null": null,
				"x-an-extension-primitive": 1,
				"x-an-extension-array": [],
				"x-an-extension-object": {},
				"description": "updates name",
				"parameters": [
					{
						"name": "name",
						"in": "query",
						"type": "string"
					},
					{
						"name": "apiKey",
						"in": "query",
						"type": "number",
						"description": "Overrides the path item parameters"
					}
				],
				"responses": {
					"204": {
						"description": "done"
					}
				}
			},
			"delete": {
				"x-an-extension-null": null,
				"x-an-extension-primitive": 1,
				"x-an-extension-array": [],
				"x-an-extension-object": {},
				"tags": [
					"foo",
					"bar",
					"baz"
				],
				"summary": "interesting endpoint which deletes something for the sake of it.",
				"externalDocs": {
					"description": "foo",
					"url": "http://www.person.com",
					"x-an-extension-null": null,
					"x-an-extension-primitive": 1,
					"x-an-extension-array": [],
					"x-an-extension-object": {}
				},
				"operationId": "deleteNameUnique",
				"consumes": [
					"application/custom+json"
				],
				"produces": [
					"application/custom+json"
				],
				"description": "deletes name",
				"parameters": [
					{
						"$ref": "#/parameters/name"
					},
					{
						"$ref": "#/parameters/fooArr"
					},
					{
						"$ref": "#/parameters/barInt"
					}
				],
				"responses": {
					"201": {
						"description": "done"
					}
				}
			},
			"put": {
				"x-an-extension-null": null,
				"x-an-extension-primitive": 1,
				"x-an-extension-array": [],
				"x-an-extension-object": {},
				"operationId": "uploadThing",
				"consumes": [
					"multipart/form-data"
				],
				"parameters": [
					{
						"x-an-extension-null": null,
						"x-an-extension-primitive": 1,
						"x-an-extension-array": [],
						"x-an-extension-object": {},
						"name": "thing",
						"in": "formData",
						"description": "file to upload",
						"required": true,
						"type": "file"
					}
				],
				"responses": {
					"default": {
						"description": "Updated"
					}
				}
			},
			"post": {
				"x-an-extension-null": null,
				"x-an-extension-primitive": 1,
				"x-an-extension-array": [],
				"x-an-extension-object": {},
				"operationId": "upsert",
				"parameters": [
					{
						"name": "thing",
						"in": "body",
						"schema": {
							"$ref": "#/definitions/wannaBeThing"
						}
					}
				],
				"schemes": [
					"http",
					"https"
				],
				"deprecated": true,
				"responses": {
					"200": {
						"x-an-extension-null": null,
						"x-an-extension-primitive": 1,
						"x-an-extension-array": [],
						"x-an-extension-object": {},
						"description": "Updated",
						"schema": {
							"$ref": "#/definitions/thing"
						},
						"headers": {
							"Location": {
								"x-an-extension-null": null,
								"x-an-extension-primitive": 1,
								"x-an-extension-array": [],
								"x-an-extension-object": {},
								"type": "string",
								"description": "Location of new resource"
							}
						},
						"examples": {
							"application/json": {
								"name": "Puma",
								"id": "Dog"
							}
						}
					},
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"type": "string",
								"description": "Location of new resource"
							}
						}
					},
					"204": {
						"description": "Updated no content"
					},
					"400": {
						"description": "Bad request",
						"schema": {
							"$ref": "#/definitions/error"
						}
					},
					"500": {
						"description": "Server error",
						"schema": {
							"$ref": "#/definitions/serverError"
						}
					},
					"501": {
						"description": "Inline schema",
						"schema": {
							"type": "object",
							"description": "why not"
						}
					},
					"x-an-extension-null": null,
					"x-an-extension-primitive": 1,
					"x-an-extension-array": [],
					"x-an-extension-object": {},
					"default": {
						"$ref": "#/responses/serverError"
					}
				}
			}
		}
	},
	"responses": {
		"serverError": {
			"description": "Server error",
			"schema": {
				"$ref": "#/definitions/serverError"
			}
		}
	},
	"definitions": {
		"geo": {
			"description": "A geographical coordinate",
			"type": "object",
			"properties": {
				"latitude": {
					"type": "number"
				},
				"longitude": {
					"type": "number"
				}
			}
		},
		"wannaBeThing": {
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {},
			"discriminator": "name",
			"type": "object",
			"properties": {
				"name": {
					"type": "string"
				}
			},
			"required": [
				"name"
			]
		},
		"thing": {
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {},
			"type": "object",
			"properties": {
				"id": {
					"type": "number"
				},
				"name": {
					"type": "string"
				}
			},
			"required": [
				"id",
				"name"
			]
		},
		"serverError": {
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {},
			"type": "object",
			"properties": {
				"message": {
					"type": "string"
				},
				"location": {
					"$ref": "#/definitions/geo"
				}
			},
			"required": [
				"message"
			]
		},
		"error": {
			"x-an-extension-null": null,
			"x-an-extension-primitive": 1,
			"x-an-extension-array": [],
			"x-an-extension-object": {},
			"type": "object",
			"properties": {
				"messages": {
					"type": "array",
					"items": {
						"type": "string"
					}
				}
			},
			"required": [
				"messages"
			]
		}
	}
}
@whitlockjc
Copy link
Member

Thanks for the report, I get what you're saying and I'll get it sorted.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants