Skip to content

Commit 9c5da05

Browse files
committed
Allow to override validate_response_callback
1 parent 7248d46 commit 9c5da05

File tree

5 files changed

+30
-10
lines changed

5 files changed

+30
-10
lines changed

docs/Usage/Response.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ def endpoint_test(body: BaseRequest):
8080
...
8181
```
8282

83+
You can also customize the default behavior of response validation by using a custom `validate_response_callback`.
84+
85+
```python
86+
87+
def validate_response_callback(response: Any, responses: Optional[ResponseDict] = None) -> Any:
88+
89+
# do something
90+
91+
return response
92+
93+
app = OpenAPI(__name__, validate_response=True, validate_response_callback=validate_response_callback)
94+
```
95+
8396
## More information about OpenAPI responses
8497

8598
- [OpenAPI Responses Object](https://spec.openapis.org/oas/v3.1.0#responses-object), it includes the Response Object.

flask_openapi3/models/components.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# @Time : 2023/7/4 9:36
44
from typing import Optional, Union, Any
55

6-
from pydantic import BaseModel, Field
6+
from pydantic import BaseModel
77

88
from .callback import Callback
99
from .example import Example
@@ -23,7 +23,7 @@ class Components(BaseModel):
2323
https://spec.openapis.org/oas/v3.1.0#components-object
2424
"""
2525

26-
schemas: Optional[dict[str, Union[Reference, Schema]]] = Field(None)
26+
schemas: Optional[dict[str, Union[Reference, Schema]]] = None
2727
responses: Optional[dict[str, Union[Response, Reference]]] = None
2828
parameters: Optional[dict[str, Union[Parameter, Reference]]] = None
2929
examples: Optional[dict[str, Union[Example, Reference]]] = None

flask_openapi3/openapi.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
from .utils import parse_and_store_tags
4343
from .utils import parse_method
4444
from .utils import parse_parameters
45+
from .utils import run_validate_response
4546
from .view import APIView
4647

4748

@@ -64,6 +65,7 @@ def __init__(
6465
doc_prefix: str = "/openapi",
6566
doc_url: str = "/openapi.json",
6667
validate_response: Optional[bool] = None,
68+
validate_response_callback: Callable = run_validate_response,
6769
**kwargs: Any
6870
) -> None:
6971
"""
@@ -97,6 +99,7 @@ def __init__(
9799
doc_url: URL for accessing the OpenAPI specification document in JSON format.
98100
Defaults to "/openapi.json".
99101
validate_response: Verify the response body.
102+
validate_response_callback: Validation and return response.
100103
**kwargs: Additional kwargs to be passed to Flask.
101104
"""
102105
super(OpenAPI, self).__init__(import_name, **kwargs)
@@ -148,6 +151,7 @@ def __init__(
148151

149152
# Verify the response body
150153
self.validate_response = validate_response
154+
self.validate_response_callback = validate_response_callback
151155

152156
# Initialize specification JSON
153157
self.spec_json: dict = {}

flask_openapi3/scaffold.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from .types import ParametersTuple
1616
from .types import ResponseDict
1717
from .utils import HTTPMethod
18-
from .utils import run_validate_response
1918

2019

2120
class APIScaffold:
@@ -105,7 +104,8 @@ async def view_func(**kwargs) -> FlaskResponse:
105104
_validate_response = validate_response
106105

107106
if _validate_response and responses:
108-
run_validate_response(response, responses)
107+
validate_response_callback = getattr(current_app, "validate_response_callback")
108+
return validate_response_callback(response, responses)
109109

110110
return response
111111
else:
@@ -141,9 +141,10 @@ def view_func(**kwargs) -> FlaskResponse:
141141
_validate_response = validate_response
142142
else:
143143
_validate_response = validate_response
144-
144+
145145
if _validate_response and responses:
146-
run_validate_response(response, responses)
146+
validate_response_callback = getattr(current_app, "validate_response_callback")
147+
return validate_response_callback(response, responses)
147148

148149
return response
149150

flask_openapi3/utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,17 +592,17 @@ def make_validation_error_response(e: ValidationError) -> FlaskResponse:
592592
return response
593593

594594

595-
def run_validate_response(response: Any, responses: Optional[ResponseDict] = None) -> None:
595+
def run_validate_response(response: Any, responses: Optional[ResponseDict] = None) -> Any:
596596
"""Validate response"""
597597
if responses is None:
598-
return
598+
return response
599599

600600
if isinstance(response, tuple): # noqa
601601
_resp, status_code = response[:2]
602602
elif isinstance(response, FlaskResponse):
603603
if response.mimetype != "application/json":
604604
# only application/json
605-
return
605+
return response
606606
_resp, status_code = response.json, response.status_code # noqa
607607
else:
608608
_resp, status_code = response, 200
@@ -614,7 +614,7 @@ def run_validate_response(response: Any, responses: Optional[ResponseDict] = Non
614614
resp_model = responses.get(status_code)
615615

616616
if resp_model is None:
617-
return
617+
return response
618618

619619
assert inspect.isclass(resp_model) and \
620620
issubclass(resp_model, BaseModel), f"{resp_model} is invalid `pydantic.BaseModel`"
@@ -624,6 +624,8 @@ def run_validate_response(response: Any, responses: Optional[ResponseDict] = Non
624624
else:
625625
resp_model.model_validate(_resp)
626626

627+
return response
628+
627629

628630
def parse_rule(rule: str, url_prefix=None) -> str:
629631
trail_slash = rule.endswith("/")

0 commit comments

Comments
 (0)