Skip to content

Commit

Permalink
fix: limit addition of OpenAPI operation fields (#245)
Browse files Browse the repository at this point in the history
  • Loading branch information
micolous authored Jan 6, 2025
1 parent d4d1632 commit 2cf6f81
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 1 deletion.
10 changes: 9 additions & 1 deletion foca/api/register_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
# Get logger instance
logger = logging.getLogger(__name__)

# Path Item object fields which contain an Operation object (ie: HTTP verbs).
# Reference: https://swagger.io/specification/v3/#path-item-object
_OPERATION_OBJECT_FIELDS = frozenset({
"get", "put", "post", "delete", "options", "head", "patch", "trace",
})


def register_openapi(
app: App,
Expand Down Expand Up @@ -51,7 +57,9 @@ def register_openapi(
if spec.add_operation_fields is not None:
for key, val in spec.add_operation_fields.items():
for path_item_object in spec_parsed.get('paths', {}).values():
for operation_object in path_item_object.values():
for operation, operation_object in path_item_object.items():
if operation not in _OPERATION_OBJECT_FIELDS:
continue
operation_object[key] = val
logger.debug(
f"Added operation fields: {spec.add_operation_fields}"
Expand Down
21 changes: 21 additions & 0 deletions tests/api/test_register_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
PATH_SPECS_2_YAML_ADDITION = DIR / "openapi_2_petstore.addition.yaml"
PATH_SPECS_3_YAML_ORIGINAL = DIR / "openapi_3_petstore.original.yaml"
PATH_SPECS_3_YAML_MODIFIED = DIR / "openapi_3_petstore.modified.yaml"
PATH_SPECS_3_PATHITEMPARAM_YAML_ORIGINAL = DIR / "openapi_3_petstore_pathitemparam.original.yaml"
PATH_SPECS_3_PATHITEMPARAM_YAML_MODIFIED = DIR / "openapi_3_petstore_pathitemparam.modified.yaml"
PATH_SPECS_INVALID_JSON = DIR / "invalid.json"
PATH_SPECS_INVALID_YAML = DIR / "invalid.openapi.yaml"
PATH_NOT_FOUND = DIR / "does/not/exist.yaml"
Expand Down Expand Up @@ -64,6 +66,15 @@
"disable_auth": False,
"connexion": CONNEXION_CONFIG,
}
SPEC_CONFIG_3_PATHITEMPARAM = {
"path": PATH_SPECS_3_PATHITEMPARAM_YAML_ORIGINAL,
"path_out": PATH_SPECS_3_PATHITEMPARAM_YAML_MODIFIED,
"append": [APPEND],
"add_operation_fields": OPERATION_FIELDS_3,
"add_security_fields": SECURITY_FIELDS_3,
"disable_auth": False,
"connexion": CONNEXION_CONFIG,
}
SPEC_CONFIG_2_JSON = deepcopy(SPEC_CONFIG_2)
SPEC_CONFIG_2_JSON['path'] = PATH_SPECS_2_JSON_ORIGINAL
SPEC_CONFIG_2_LIST = deepcopy(SPEC_CONFIG_2)
Expand Down Expand Up @@ -92,6 +103,16 @@ def test_openapi_3_yaml(self):
res = register_openapi(app=app, specs=spec_configs)
assert isinstance(res, App)

def test_openapi_3_pathitemparam_yaml(self):
"""
Successfully register OpenAPI 3 YAML specs with PathItem.parameters
field with Connexion app.
"""
app = App(__name__)
spec_configs = [SpecConfig(**SPEC_CONFIG_3_PATHITEMPARAM)]
res = register_openapi(app=app, specs=spec_configs)
assert isinstance(res, App)

def test_openapi_2_json(self):
"""Successfully register OpenAPI 2 JSON specs with Connexion app."""
app = App(__name__)
Expand Down
114 changes: 114 additions & 0 deletions tests/test_files/openapi_3_petstore_pathitemparam.modified.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
components:
schemas:
Error:
properties:
code:
format: int32
type: integer
message:
type: string
required:
- code
- message
type: object
Pet:
properties:
id:
format: int64
type: integer
name:
type: string
tag:
type: string
required:
- id
- name
type: object
Pets:
items:
$ref: '#/components/schemas/Pet'
type: array
info:
license:
name: MIT
title: Swagger Petstore
version: 1.0.0
openapi: 3.0.0
paths:
/pets:
get:
operationId: listPets
parameters:
- description: How many items to return at one time (max 100)
in: query
name: limit
required: false
schema:
format: int32
type: integer
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Pets'
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unexpected error
summary: List all pets
tags:
- pets
x-openapi-router-controller: controllers
post:
operationId: createPets
responses:
'201':
description: Null response
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unexpected error
summary: Create a pet
tags:
- pets
x-openapi-router-controller: controllers
/pets/{petId}:
parameters:
- description: The id of the pet to retrieve
in: path
name: petId
required: true
schema:
type: string
get:
operationId: showPetById
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
description: Expected response to a valid request
default:
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
description: unexpected error
summary: Info for a specific pet
tags:
- pets
x-openapi-router-controller: controllers
servers:
- url: http://petstore.swagger.io/v2
122 changes: 122 additions & 0 deletions tests/test_files/openapi_3_petstore_pathitemparam.original.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v2
security:
- bearerAuth: []
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: A 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"
security:
- bearerAuth: []
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"
security:
- bearerAuth: []
/pets/{petId}:
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string

0 comments on commit 2cf6f81

Please sign in to comment.