Skip to content

Commit 45dd535

Browse files
author
Marwen Taleb
committed
fix: check duplicates schemas when loading swagger
1 parent a29b4f9 commit 45dd535

File tree

6 files changed

+418
-31
lines changed

6 files changed

+418
-31
lines changed

openapi_spec_validator/handlers/compat.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,36 @@
44
except ImportError:
55
from yaml import SafeLoader
66

7+
from jsonschema.exceptions import ValidationError
78

8-
__all__ = ['SafeLoader', ]
9+
10+
class UniqueSchemasLoader(SafeLoader):
11+
"""Loader that checks that schemas definitions are unique"""
12+
13+
POSSIBLE_SCHEMAS_YAML_PATHS = ["definitions", "components.schemas"]
14+
15+
def construct_mapping(self, node, deep=True):
16+
self._check_for_duplicate_schemas_definitions(node, deep, self.POSSIBLE_SCHEMAS_YAML_PATHS)
17+
return super().construct_mapping(node, deep)
18+
19+
def _check_for_duplicate_schemas_definitions(self, node, deep, possible_schemas_yaml_paths):
20+
for schemas_yaml_path in possible_schemas_yaml_paths:
21+
keys = []
22+
for key_node, value_node in node.value:
23+
if schemas_yaml_path:
24+
if key_node.value == schemas_yaml_path.split(".")[0]:
25+
return self._check_for_duplicate_schemas_definitions(
26+
value_node,
27+
deep,
28+
possible_schemas_yaml_paths=[
29+
".".join(schemas_yaml_path.split(".")[1:])
30+
],
31+
)
32+
else:
33+
key = self.construct_object(key_node, deep=deep)
34+
if key in keys:
35+
raise ValidationError(f"Duplicate definition for {key} schema.")
36+
keys.append(key)
37+
38+
39+
__all__ = ["SafeLoader", "UniqueSchemasLoader"]

openapi_spec_validator/handlers/file.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
from yaml import load
66

77
from openapi_spec_validator.handlers.base import BaseHandler
8-
from openapi_spec_validator.handlers.compat import SafeLoader
8+
from openapi_spec_validator.handlers.compat import UniqueSchemasLoader
99
from openapi_spec_validator.handlers.utils import uri_to_path
1010

1111

1212
class FileObjectHandler(BaseHandler):
1313
"""OpenAPI spec validator file-like object handler."""
1414

15-
def __init__(self, loader=SafeLoader):
15+
def __init__(self, loader=UniqueSchemasLoader):
1616
self.loader = loader
1717

1818
def __call__(self, f):
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
swagger: "2.0"
2+
info:
3+
version: 1.0.0
4+
title: Swagger Petstore
5+
license:
6+
name: MIT
7+
host: petstore.swagger.io
8+
basePath: /v1
9+
schemes:
10+
- http
11+
consumes:
12+
- application/json
13+
produces:
14+
- application/json
15+
paths:
16+
/pets:
17+
get:
18+
summary: List all pets
19+
operationId: listPets
20+
tags:
21+
- pets
22+
parameters:
23+
- name: limit
24+
in: query
25+
description: How many items to return at one time (max 100)
26+
required: false
27+
type: integer
28+
format: int32
29+
responses:
30+
200:
31+
description: A paged array of pets
32+
headers:
33+
x-next:
34+
type: string
35+
description: A link to the next page of responses
36+
schema:
37+
$ref: '#/definitions/Pets'
38+
default:
39+
description: unexpected error
40+
schema:
41+
$ref: '#/definitions/Error'
42+
post:
43+
summary: Create a pet
44+
operationId: createPets
45+
tags:
46+
- pets
47+
responses:
48+
'201':
49+
description: Null response
50+
default:
51+
description: unexpected error
52+
schema:
53+
$ref: '#/definitions/Error'
54+
/pets/{petId}:
55+
get:
56+
summary: Info for a specific pet
57+
operationId: showPetById
58+
tags:
59+
- pets
60+
parameters:
61+
- name: petId
62+
in: path
63+
required: true
64+
description: The id of the pet to retrieve
65+
type: string
66+
responses:
67+
'200':
68+
description: Expected response to a valid request
69+
schema:
70+
$ref: '#/definitions/Pets'
71+
default:
72+
description: unexpected error
73+
schema:
74+
$ref: '#/definitions/Error'
75+
definitions:
76+
Pet:
77+
required:
78+
- id
79+
- name
80+
properties:
81+
id:
82+
type: integer
83+
format: int64
84+
name:
85+
type: string
86+
tag:
87+
type: string
88+
Pet:
89+
required:
90+
- id
91+
- name
92+
properties:
93+
id:
94+
type: integer
95+
format: int64
96+
name:
97+
type: string
98+
tag:
99+
type: string
100+
Pets:
101+
type: array
102+
items:
103+
$ref: '#/definitions/Pet'
104+
Error:
105+
required:
106+
- code
107+
- message
108+
properties:
109+
code:
110+
type: integer
111+
format: int32
112+
message:
113+
type: string
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
openapi: "3.0.0"
2+
info:
3+
version: 1.0.0
4+
title: Swagger Petstore
5+
license:
6+
name: MIT
7+
servers:
8+
- url: http://petstore.swagger.io/v1
9+
paths:
10+
/pets:
11+
get:
12+
summary: List all pets
13+
operationId: listPets
14+
tags:
15+
- pets
16+
parameters:
17+
- name: limit
18+
in: query
19+
description: How many items to return at one time (max 100)
20+
required: false
21+
schema:
22+
type: integer
23+
format: int32
24+
responses:
25+
200:
26+
description: An paged array of pets
27+
headers:
28+
x-next:
29+
description: A link to the next page of responses
30+
schema:
31+
type: string
32+
content:
33+
application/json:
34+
schema:
35+
$ref: "#/components/schemas/Pets"
36+
default:
37+
description: unexpected error
38+
content:
39+
application/json:
40+
schema:
41+
$ref: "#/components/schemas/Error"
42+
post:
43+
summary: Create a pet
44+
operationId: createPets
45+
tags:
46+
- pets
47+
responses:
48+
'201':
49+
description: Null response
50+
default:
51+
description: unexpected error
52+
content:
53+
application/json:
54+
schema:
55+
$ref: "#/components/schemas/Error"
56+
/pets/{petId}:
57+
get:
58+
summary: Info for a specific pet
59+
operationId: showPetById
60+
tags:
61+
- pets
62+
parameters:
63+
- name: petId
64+
in: path
65+
required: true
66+
description: The id of the pet to retrieve
67+
schema:
68+
type: string
69+
responses:
70+
'200':
71+
description: Expected response to a valid request
72+
content:
73+
application/json:
74+
schema:
75+
$ref: "#/components/schemas/Pets"
76+
default:
77+
description: unexpected error
78+
content:
79+
application/json:
80+
schema:
81+
$ref: "#/components/schemas/Error"
82+
components:
83+
schemas:
84+
Pet:
85+
required:
86+
- id
87+
- name
88+
properties:
89+
id:
90+
type: integer
91+
format: int64
92+
name:
93+
type: string
94+
tag:
95+
type: string
96+
$ref:
97+
type: string
98+
Pets:
99+
type: array
100+
items:
101+
$ref: "#/components/schemas/Pet"
102+
Pets:
103+
type: array
104+
items:
105+
$ref: "#/components/schemas/Pet"
106+
Error:
107+
required:
108+
- code
109+
- message
110+
properties:
111+
code:
112+
type: integer
113+
format: int32
114+
message:
115+
type: string

0 commit comments

Comments
 (0)