Skip to content

Commit 19bacfd

Browse files
committed
Validators refactor
1 parent 706a7ea commit 19bacfd

24 files changed

+652
-339
lines changed

README.rst

+11-9
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,20 @@ Alternatively you can download the code and install from the repository:
5858
Usage
5959
#####
6060

61-
Firstly create your specification object. By default, OpenAPI spec version is detected:
61+
Firstly create your specification object.
6262

6363
.. code-block:: python
6464
6565
from openapi_core import Spec
6666
6767
spec = Spec.from_file_path('openapi.json')
6868
69+
Now you can use it to validate against requests and/or responses.
70+
6971
Request
7072
*******
7173

72-
Now you can use it to validate against requests
74+
Use ``validate_request`` function to validate request against a given spec.
7375

7476
.. code-block:: python
7577
@@ -78,7 +80,7 @@ Now you can use it to validate against requests
7880
# raise error if request is invalid
7981
result = validate_request(request, spec=spec)
8082
81-
and unmarshal request data from validation result
83+
Retrieve request data from validation result
8284

8385
.. code-block:: python
8486
@@ -98,7 +100,7 @@ Request object should implement OpenAPI Request protocol (See `Integrations <htt
98100
Response
99101
********
100102

101-
You can also validate against responses
103+
Use ``validate_response`` function to validate response against a given spec.
102104

103105
.. code-block:: python
104106
@@ -121,16 +123,16 @@ Response object should implement OpenAPI Response protocol (See `Integrations <h
121123

122124
In order to explicitly validate a:
123125

124-
* OpenAPI 3.0 spec, import ``openapi_v30_request_validator`` or ``openapi_v30_response_validator``
125-
* OpenAPI 3.1 spec, import ``openapi_v31_request_validator`` or ``openapi_v31_response_validator``
126+
* OpenAPI 3.0 spec, import ``V30RequestValidator`` or ``V30ResponseValidator``
127+
* OpenAPI 3.1 spec, import ``V31RequestValidator`` or ``V31ResponseValidator``
126128

127129
.. code:: python
128130
129-
from openapi_core import openapi_v31_response_validator
131+
from openapi_core import V31ResponseValidator
130132
131-
result = validate_response(request, response, spec=spec, validator=openapi_v31_response_validator)
133+
result = validate_response(request, response, spec=spec, cls=V31ResponseValidator)
132134
133-
You can also explicitly import ``openapi_v3_request_validator`` or ``openapi_v3_response_validator`` which is a shortcut to the latest v3 release.
135+
You can also explicitly import ``V3RequestValidator`` or ``V3ResponseValidator`` which is a shortcut to the latest v3 release.
134136

135137
Related projects
136138
################

docs/customizations.rst

+10-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Pass custom defined media type deserializers dictionary with supported mimetypes
2222
.. code-block:: python
2323
2424
from openapi_core.deserializing.media_types.factories import MediaTypeDeserializersFactory
25-
from openapi_core.unmarshalling.schemas import oas30_response_schema_unmarshallers_factory
2625
2726
def protobuf_deserializer(message):
2827
feature = route_guide_pb2.Feature()
@@ -36,13 +35,13 @@ Pass custom defined media type deserializers dictionary with supported mimetypes
3635
custom_deserializers=custom_media_type_deserializers,
3736
)
3837
39-
validator = ResponseValidator(
40-
oas30_response_schema_unmarshallers_factory,
38+
result = validate_response(
39+
request, response,
40+
spec=spec,
41+
cls=V30ResponseValidator,
4142
media_type_deserializers_factory=media_type_deserializers_factory,
4243
)
4344
44-
result = validator.validate(spec, request, response)
45-
4645
Formats
4746
-------
4847

@@ -75,7 +74,11 @@ Here's how you could add support for a ``usdate`` format that handles dates of t
7574
custom_formatters=custom_formatters,
7675
context=UnmarshalContext.RESPONSE,
7776
)
78-
validator = ResponseValidator(schema_unmarshallers_factory)
7977
80-
result = validator.validate(spec, request, response)
78+
result = validate_response(
79+
request, response,
80+
spec=spec,
81+
cls=ResponseValidator,
82+
schema_unmarshallers_factory=schema_unmarshallers_factory,
83+
)
8184

docs/usage.rst

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
Usage
22
=====
33

4-
Firstly create your specification object. By default, OpenAPI spec version is detected:
4+
Firstly create your specification object.
55

66
.. code-block:: python
77
88
from openapi_core import Spec
99
1010
spec = Spec.from_file_path('openapi.json')
1111
12+
Now you can use it to validate against requests and/or responses.
1213

1314
Request
1415
-------
1516

16-
Now you can use it to validate against requests
17+
Use ``validate_request`` function to validate request against a given spec. By default, OpenAPI spec version is detected:
1718

1819
.. code-block:: python
1920
@@ -22,7 +23,7 @@ Now you can use it to validate against requests
2223
# raise error if request is invalid
2324
result = validate_request(request, spec=spec)
2425
25-
and unmarshal request data from validation result
26+
Retrieve validated and unmarshalled request data from validation result
2627

2728
.. code-block:: python
2829
@@ -42,7 +43,7 @@ Request object should implement OpenAPI Request protocol (See :doc:`integrations
4243
Response
4344
--------
4445

45-
You can also validate against responses
46+
Use ``validate_response`` function to validate response against a given spec. By default, OpenAPI spec version is detected:
4647

4748
.. code-block:: python
4849
@@ -51,7 +52,7 @@ You can also validate against responses
5152
# raise error if response is invalid
5253
result = validate_response(request, response, spec=spec)
5354
54-
and unmarshal response data from validation result
55+
Retrieve validated and unmarshalled response data from validation result
5556

5657
.. code-block:: python
5758
@@ -89,8 +90,6 @@ you can access your security data the following:
8990

9091
.. code-block:: python
9192
92-
result = validator.validate(request)
93-
9493
# get basic auth decoded credentials
9594
result.security['BasicAuth']
9695

openapi_core/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""OpenAPI core module"""
22
from openapi_core.spec import Spec
3+
from openapi_core.validation.request import V3RequestValidator
4+
from openapi_core.validation.request import V30RequestValidator
5+
from openapi_core.validation.request import V31RequestValidator
36
from openapi_core.validation.request import openapi_request_body_validator
47
from openapi_core.validation.request import (
58
openapi_request_parameters_validator,
@@ -9,6 +12,9 @@
912
from openapi_core.validation.request import openapi_v3_request_validator
1013
from openapi_core.validation.request import openapi_v30_request_validator
1114
from openapi_core.validation.request import openapi_v31_request_validator
15+
from openapi_core.validation.response import V3ResponseValidator
16+
from openapi_core.validation.response import V30ResponseValidator
17+
from openapi_core.validation.response import V31ResponseValidator
1218
from openapi_core.validation.response import openapi_response_data_validator
1319
from openapi_core.validation.response import openapi_response_headers_validator
1420
from openapi_core.validation.response import openapi_response_validator
@@ -28,6 +34,12 @@
2834
"Spec",
2935
"validate_request",
3036
"validate_response",
37+
"V30RequestValidator",
38+
"V31RequestValidator",
39+
"V3RequestValidator",
40+
"V30ResponseValidator",
41+
"V31ResponseValidator",
42+
"V3ResponseValidator",
3143
"openapi_v3_request_validator",
3244
"openapi_v30_request_validator",
3345
"openapi_v31_request_validator",

openapi_core/contrib/django/middlewares.py

+3-11
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@
1111
from openapi_core.contrib.django.requests import DjangoOpenAPIRequest
1212
from openapi_core.contrib.django.responses import DjangoOpenAPIResponse
1313
from openapi_core.validation.processors import OpenAPIProcessor
14-
from openapi_core.validation.request import openapi_request_validator
1514
from openapi_core.validation.request.datatypes import RequestValidationResult
16-
from openapi_core.validation.request.protocols import Request
17-
from openapi_core.validation.response import openapi_response_validator
1815
from openapi_core.validation.response.datatypes import ResponseValidationResult
19-
from openapi_core.validation.response.protocols import Response
2016

2117

2218
class DjangoOpenAPIMiddleware:
@@ -31,15 +27,11 @@ def __init__(self, get_response: Callable[[HttpRequest], HttpResponse]):
3127
if not hasattr(settings, "OPENAPI_SPEC"):
3228
raise ImproperlyConfigured("OPENAPI_SPEC not defined in settings")
3329

34-
self.validation_processor = OpenAPIProcessor(
35-
openapi_request_validator, openapi_response_validator
36-
)
30+
self.validation_processor = OpenAPIProcessor(settings.OPENAPI_SPEC)
3731

3832
def __call__(self, request: HttpRequest) -> HttpResponse:
3933
openapi_request = self._get_openapi_request(request)
40-
req_result = self.validation_processor.process_request(
41-
settings.OPENAPI_SPEC, openapi_request
42-
)
34+
req_result = self.validation_processor.process_request(openapi_request)
4335
if req_result.errors:
4436
response = self._handle_request_errors(req_result, request)
4537
else:
@@ -48,7 +40,7 @@ def __call__(self, request: HttpRequest) -> HttpResponse:
4840

4941
openapi_response = self._get_openapi_response(response)
5042
resp_result = self.validation_processor.process_response(
51-
settings.OPENAPI_SPEC, openapi_request, openapi_response
43+
openapi_request, openapi_response
5244
)
5345
if resp_result.errors:
5446
return self._handle_response_errors(resp_result, request, response)

openapi_core/contrib/falcon/middlewares.py

+18-30
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
from openapi_core.contrib.falcon.responses import FalconOpenAPIResponse
1212
from openapi_core.spec import Spec
1313
from openapi_core.validation.processors import OpenAPIProcessor
14-
from openapi_core.validation.request import openapi_request_validator
1514
from openapi_core.validation.request.datatypes import RequestValidationResult
16-
from openapi_core.validation.response import openapi_response_validator
15+
from openapi_core.validation.request.protocols import RequestValidator
1716
from openapi_core.validation.response.datatypes import ResponseValidationResult
17+
from openapi_core.validation.response.protocols import ResponseValidator
1818

1919

20-
class FalconOpenAPIMiddleware:
20+
class FalconOpenAPIMiddleware(OpenAPIProcessor):
2121

2222
request_class = FalconOpenAPIRequest
2323
response_class = FalconOpenAPIResponse
@@ -26,13 +26,17 @@ class FalconOpenAPIMiddleware:
2626
def __init__(
2727
self,
2828
spec: Spec,
29-
validation_processor: OpenAPIProcessor,
29+
request_validator_cls: Optional[Type[RequestValidator]] = None,
30+
response_validator_cls: Optional[Type[ResponseValidator]] = None,
3031
request_class: Type[FalconOpenAPIRequest] = FalconOpenAPIRequest,
3132
response_class: Type[FalconOpenAPIResponse] = FalconOpenAPIResponse,
3233
errors_handler: Optional[FalconOpenAPIErrorsHandler] = None,
3334
):
34-
self.spec = spec
35-
self.validation_processor = validation_processor
35+
super().__init__(
36+
spec,
37+
request_validator_cls=request_validator_cls,
38+
response_validator_cls=response_validator_cls,
39+
)
3640
self.request_class = request_class or self.request_class
3741
self.response_class = response_class or self.response_class
3842
self.errors_handler = errors_handler or self.errors_handler
@@ -41,33 +45,33 @@ def __init__(
4145
def from_spec(
4246
cls,
4347
spec: Spec,
48+
request_validator_cls: Optional[Type[RequestValidator]] = None,
49+
response_validator_cls: Optional[Type[ResponseValidator]] = None,
4450
request_class: Type[FalconOpenAPIRequest] = FalconOpenAPIRequest,
4551
response_class: Type[FalconOpenAPIResponse] = FalconOpenAPIResponse,
4652
errors_handler: Optional[FalconOpenAPIErrorsHandler] = None,
4753
) -> "FalconOpenAPIMiddleware":
48-
validation_processor = OpenAPIProcessor(
49-
openapi_request_validator, openapi_response_validator
50-
)
5154
return cls(
5255
spec,
53-
validation_processor,
56+
request_validator_cls=request_validator_cls,
57+
response_validator_cls=response_validator_cls,
5458
request_class=request_class,
5559
response_class=response_class,
5660
errors_handler=errors_handler,
5761
)
5862

59-
def process_request(self, req: Request, resp: Response) -> None:
63+
def process_request(self, req: Request, resp: Response) -> None: # type: ignore
6064
openapi_req = self._get_openapi_request(req)
61-
req.context.openapi = self._process_openapi_request(openapi_req)
65+
req.context.openapi = super().process_request(openapi_req)
6266
if req.context.openapi.errors:
6367
return self._handle_request_errors(req, resp, req.context.openapi)
6468

65-
def process_response(
69+
def process_response( # type: ignore
6670
self, req: Request, resp: Response, resource: Any, req_succeeded: bool
6771
) -> None:
6872
openapi_req = self._get_openapi_request(req)
6973
openapi_resp = self._get_openapi_response(resp)
70-
resp.context.openapi = self._process_openapi_response(
74+
resp.context.openapi = super().process_response(
7175
openapi_req, openapi_resp
7276
)
7377
if resp.context.openapi.errors:
@@ -98,19 +102,3 @@ def _get_openapi_response(
98102
self, response: Response
99103
) -> FalconOpenAPIResponse:
100104
return self.response_class(response)
101-
102-
def _process_openapi_request(
103-
self, openapi_request: FalconOpenAPIRequest
104-
) -> RequestValidationResult:
105-
return self.validation_processor.process_request(
106-
self.spec, openapi_request
107-
)
108-
109-
def _process_openapi_response(
110-
self,
111-
opneapi_request: FalconOpenAPIRequest,
112-
openapi_response: FalconOpenAPIResponse,
113-
) -> ResponseValidationResult:
114-
return self.validation_processor.process_response(
115-
self.spec, opneapi_request, openapi_response
116-
)

0 commit comments

Comments
 (0)