Skip to content

Commit

Permalink
fix: check duplicates schemas when loading swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
Marwen Taleb committed Jun 22, 2022
1 parent a29b4f9 commit 45dd535
Show file tree
Hide file tree
Showing 6 changed files with 418 additions and 31 deletions.
33 changes: 32 additions & 1 deletion openapi_spec_validator/handlers/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,36 @@
except ImportError:
from yaml import SafeLoader

from jsonschema.exceptions import ValidationError

__all__ = ['SafeLoader', ]

class UniqueSchemasLoader(SafeLoader):
"""Loader that checks that schemas definitions are unique"""

POSSIBLE_SCHEMAS_YAML_PATHS = ["definitions", "components.schemas"]

def construct_mapping(self, node, deep=True):
self._check_for_duplicate_schemas_definitions(node, deep, self.POSSIBLE_SCHEMAS_YAML_PATHS)
return super().construct_mapping(node, deep)

def _check_for_duplicate_schemas_definitions(self, node, deep, possible_schemas_yaml_paths):
for schemas_yaml_path in possible_schemas_yaml_paths:
keys = []
for key_node, value_node in node.value:
if schemas_yaml_path:
if key_node.value == schemas_yaml_path.split(".")[0]:
return self._check_for_duplicate_schemas_definitions(
value_node,
deep,
possible_schemas_yaml_paths=[
".".join(schemas_yaml_path.split(".")[1:])
],
)
else:
key = self.construct_object(key_node, deep=deep)
if key in keys:
raise ValidationError(f"Duplicate definition for {key} schema.")
keys.append(key)


__all__ = ["SafeLoader", "UniqueSchemasLoader"]
4 changes: 2 additions & 2 deletions openapi_spec_validator/handlers/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
from yaml import load

from openapi_spec_validator.handlers.base import BaseHandler
from openapi_spec_validator.handlers.compat import SafeLoader
from openapi_spec_validator.handlers.compat import UniqueSchemasLoader
from openapi_spec_validator.handlers.utils import uri_to_path


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

def __init__(self, loader=SafeLoader):
def __init__(self, loader=UniqueSchemasLoader):
self.loader = loader

def __call__(self, f):
Expand Down
113 changes: 113 additions & 0 deletions tests/integration/data/v2.0/petstore_duplicate_schemas_def.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
swagger: "2.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
host: petstore.swagger.io
basePath: /v1
schemes:
- http
consumes:
- application/json
produces:
- application/json
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
type: integer
format: int32
responses:
200:
description: A paged array of pets
headers:
x-next:
type: string
description: A link to the next page of responses
schema:
$ref: '#/definitions/Pets'
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
type: string
responses:
'200':
description: Expected response to a valid request
schema:
$ref: '#/definitions/Pets'
default:
description: unexpected error
schema:
$ref: '#/definitions/Error'
definitions:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: '#/definitions/Pet'
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
115 changes: 115 additions & 0 deletions tests/integration/data/v3.0/petstore_duplicate_schemas_def.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
200:
description: An paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
$ref:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
Loading

0 comments on commit 45dd535

Please sign in to comment.