Skip to content

Commit 2cf6f81

Browse files
authored
fix: limit addition of OpenAPI operation fields (#245)
1 parent d4d1632 commit 2cf6f81

4 files changed

+266
-1
lines changed

foca/api/register_openapi.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
# Get logger instance
1313
logger = logging.getLogger(__name__)
1414

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

1622
def register_openapi(
1723
app: App,
@@ -51,7 +57,9 @@ def register_openapi(
5157
if spec.add_operation_fields is not None:
5258
for key, val in spec.add_operation_fields.items():
5359
for path_item_object in spec_parsed.get('paths', {}).values():
54-
for operation_object in path_item_object.values():
60+
for operation, operation_object in path_item_object.items():
61+
if operation not in _OPERATION_OBJECT_FIELDS:
62+
continue
5563
operation_object[key] = val
5664
logger.debug(
5765
f"Added operation fields: {spec.add_operation_fields}"

tests/api/test_register_openapi.py

+21
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
PATH_SPECS_2_YAML_ADDITION = DIR / "openapi_2_petstore.addition.yaml"
2222
PATH_SPECS_3_YAML_ORIGINAL = DIR / "openapi_3_petstore.original.yaml"
2323
PATH_SPECS_3_YAML_MODIFIED = DIR / "openapi_3_petstore.modified.yaml"
24+
PATH_SPECS_3_PATHITEMPARAM_YAML_ORIGINAL = DIR / "openapi_3_petstore_pathitemparam.original.yaml"
25+
PATH_SPECS_3_PATHITEMPARAM_YAML_MODIFIED = DIR / "openapi_3_petstore_pathitemparam.modified.yaml"
2426
PATH_SPECS_INVALID_JSON = DIR / "invalid.json"
2527
PATH_SPECS_INVALID_YAML = DIR / "invalid.openapi.yaml"
2628
PATH_NOT_FOUND = DIR / "does/not/exist.yaml"
@@ -64,6 +66,15 @@
6466
"disable_auth": False,
6567
"connexion": CONNEXION_CONFIG,
6668
}
69+
SPEC_CONFIG_3_PATHITEMPARAM = {
70+
"path": PATH_SPECS_3_PATHITEMPARAM_YAML_ORIGINAL,
71+
"path_out": PATH_SPECS_3_PATHITEMPARAM_YAML_MODIFIED,
72+
"append": [APPEND],
73+
"add_operation_fields": OPERATION_FIELDS_3,
74+
"add_security_fields": SECURITY_FIELDS_3,
75+
"disable_auth": False,
76+
"connexion": CONNEXION_CONFIG,
77+
}
6778
SPEC_CONFIG_2_JSON = deepcopy(SPEC_CONFIG_2)
6879
SPEC_CONFIG_2_JSON['path'] = PATH_SPECS_2_JSON_ORIGINAL
6980
SPEC_CONFIG_2_LIST = deepcopy(SPEC_CONFIG_2)
@@ -92,6 +103,16 @@ def test_openapi_3_yaml(self):
92103
res = register_openapi(app=app, specs=spec_configs)
93104
assert isinstance(res, App)
94105

106+
def test_openapi_3_pathitemparam_yaml(self):
107+
"""
108+
Successfully register OpenAPI 3 YAML specs with PathItem.parameters
109+
field with Connexion app.
110+
"""
111+
app = App(__name__)
112+
spec_configs = [SpecConfig(**SPEC_CONFIG_3_PATHITEMPARAM)]
113+
res = register_openapi(app=app, specs=spec_configs)
114+
assert isinstance(res, App)
115+
95116
def test_openapi_2_json(self):
96117
"""Successfully register OpenAPI 2 JSON specs with Connexion app."""
97118
app = App(__name__)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
components:
2+
schemas:
3+
Error:
4+
properties:
5+
code:
6+
format: int32
7+
type: integer
8+
message:
9+
type: string
10+
required:
11+
- code
12+
- message
13+
type: object
14+
Pet:
15+
properties:
16+
id:
17+
format: int64
18+
type: integer
19+
name:
20+
type: string
21+
tag:
22+
type: string
23+
required:
24+
- id
25+
- name
26+
type: object
27+
Pets:
28+
items:
29+
$ref: '#/components/schemas/Pet'
30+
type: array
31+
info:
32+
license:
33+
name: MIT
34+
title: Swagger Petstore
35+
version: 1.0.0
36+
openapi: 3.0.0
37+
paths:
38+
/pets:
39+
get:
40+
operationId: listPets
41+
parameters:
42+
- description: How many items to return at one time (max 100)
43+
in: query
44+
name: limit
45+
required: false
46+
schema:
47+
format: int32
48+
type: integer
49+
responses:
50+
'200':
51+
content:
52+
application/json:
53+
schema:
54+
$ref: '#/components/schemas/Pets'
55+
description: A paged array of pets
56+
headers:
57+
x-next:
58+
description: A link to the next page of responses
59+
schema:
60+
type: string
61+
default:
62+
content:
63+
application/json:
64+
schema:
65+
$ref: '#/components/schemas/Error'
66+
description: unexpected error
67+
summary: List all pets
68+
tags:
69+
- pets
70+
x-openapi-router-controller: controllers
71+
post:
72+
operationId: createPets
73+
responses:
74+
'201':
75+
description: Null response
76+
default:
77+
content:
78+
application/json:
79+
schema:
80+
$ref: '#/components/schemas/Error'
81+
description: unexpected error
82+
summary: Create a pet
83+
tags:
84+
- pets
85+
x-openapi-router-controller: controllers
86+
/pets/{petId}:
87+
parameters:
88+
- description: The id of the pet to retrieve
89+
in: path
90+
name: petId
91+
required: true
92+
schema:
93+
type: string
94+
get:
95+
operationId: showPetById
96+
responses:
97+
'200':
98+
content:
99+
application/json:
100+
schema:
101+
$ref: '#/components/schemas/Pet'
102+
description: Expected response to a valid request
103+
default:
104+
content:
105+
application/json:
106+
schema:
107+
$ref: '#/components/schemas/Error'
108+
description: unexpected error
109+
summary: Info for a specific pet
110+
tags:
111+
- pets
112+
x-openapi-router-controller: controllers
113+
servers:
114+
- url: http://petstore.swagger.io/v2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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/v2
9+
security:
10+
- bearerAuth: []
11+
paths:
12+
/pets:
13+
get:
14+
summary: List all pets
15+
operationId: listPets
16+
tags:
17+
- pets
18+
parameters:
19+
- name: limit
20+
in: query
21+
description: How many items to return at one time (max 100)
22+
required: false
23+
schema:
24+
type: integer
25+
format: int32
26+
responses:
27+
'200':
28+
description: A paged array of pets
29+
headers:
30+
x-next:
31+
description: A link to the next page of responses
32+
schema:
33+
type: string
34+
content:
35+
application/json:
36+
schema:
37+
$ref: "#/components/schemas/Pets"
38+
default:
39+
description: unexpected error
40+
content:
41+
application/json:
42+
schema:
43+
$ref: "#/components/schemas/Error"
44+
security:
45+
- bearerAuth: []
46+
post:
47+
summary: Create a pet
48+
operationId: createPets
49+
tags:
50+
- pets
51+
responses:
52+
'201':
53+
description: Null response
54+
default:
55+
description: unexpected error
56+
content:
57+
application/json:
58+
schema:
59+
$ref: "#/components/schemas/Error"
60+
security:
61+
- bearerAuth: []
62+
/pets/{petId}:
63+
parameters:
64+
- name: petId
65+
in: path
66+
required: true
67+
description: The id of the pet to retrieve
68+
schema:
69+
type: string
70+
get:
71+
summary: Info for a specific pet
72+
operationId: showPetById
73+
tags:
74+
- pets
75+
responses:
76+
'200':
77+
description: Expected response to a valid request
78+
content:
79+
application/json:
80+
schema:
81+
$ref: "#/components/schemas/Pet"
82+
default:
83+
description: unexpected error
84+
content:
85+
application/json:
86+
schema:
87+
$ref: "#/components/schemas/Error"
88+
components:
89+
securitySchemes:
90+
bearerAuth:
91+
type: http
92+
scheme: bearer
93+
bearerFormat: JWT
94+
schemas:
95+
Pet:
96+
type: object
97+
required:
98+
- id
99+
- name
100+
properties:
101+
id:
102+
type: integer
103+
format: int64
104+
name:
105+
type: string
106+
tag:
107+
type: string
108+
Pets:
109+
type: array
110+
items:
111+
$ref: "#/components/schemas/Pet"
112+
Error:
113+
type: object
114+
required:
115+
- code
116+
- message
117+
properties:
118+
code:
119+
type: integer
120+
format: int32
121+
message:
122+
type: string

0 commit comments

Comments
 (0)