Skip to content

Predefined openapi validators #409

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions openapi_core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
"""OpenAPI core module"""
from openapi_core.spec import OpenAPIv30Spec
from openapi_core.validation.request.shortcuts import validate_request
from openapi_core.validation.request.validators import RequestBodyValidator
from openapi_core.validation.request.validators import (
RequestParametersValidator,
)
from openapi_core.validation.request.validators import RequestSecurityValidator
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.shortcuts import validate_response
from openapi_core.validation.response.validators import ResponseDataValidator
from openapi_core.validation.response.validators import (
ResponseHeadersValidator,
)
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.validation.shortcuts import validate_request
from openapi_core.validation.shortcuts import validate_response

__author__ = "Artur Maciag"
__email__ = "[email protected]"
Expand Down
2 changes: 1 addition & 1 deletion openapi_core/contrib/django/handlers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""OpenAPI core contrib django handlers module"""
from django.http import JsonResponse

from openapi_core.exceptions import MissingRequiredParameter
from openapi_core.templating.media_types.exceptions import MediaTypeNotFound
from openapi_core.templating.paths.exceptions import OperationNotFound
from openapi_core.templating.paths.exceptions import PathNotFound
from openapi_core.templating.paths.exceptions import ServerNotFound
from openapi_core.validation.exceptions import InvalidSecurity
from openapi_core.validation.exceptions import MissingRequiredParameter


class DjangoOpenAPIErrorsHandler:
Expand Down
14 changes: 7 additions & 7 deletions openapi_core/contrib/django/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from openapi_core.contrib.django.requests import DjangoOpenAPIRequest
from openapi_core.contrib.django.responses import DjangoOpenAPIResponse
from openapi_core.validation.processors import OpenAPIProcessor
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.validation.request import openapi_request_validator
from openapi_core.validation.response import openapi_response_validator


class DjangoOpenAPIMiddleware:
Expand All @@ -22,15 +22,15 @@ def __init__(self, get_response):
if not hasattr(settings, "OPENAPI_SPEC"):
raise ImproperlyConfigured("OPENAPI_SPEC not defined in settings")

request_validator = RequestValidator(settings.OPENAPI_SPEC)
response_validator = ResponseValidator(settings.OPENAPI_SPEC)
self.validation_processor = OpenAPIProcessor(
request_validator, response_validator
openapi_request_validator, openapi_response_validator
)

def __call__(self, request):
openapi_request = self._get_openapi_request(request)
req_result = self.validation_processor.process_request(openapi_request)
req_result = self.validation_processor.process_request(
settings.OPENAPI_SPEC, openapi_request
)
if req_result.errors:
response = self._handle_request_errors(req_result, request)
else:
Expand All @@ -39,7 +39,7 @@ def __call__(self, request):

openapi_response = self._get_openapi_response(response)
resp_result = self.validation_processor.process_response(
openapi_request, openapi_response
settings.OPENAPI_SPEC, openapi_request, openapi_response
)
if resp_result.errors:
return self._handle_response_errors(resp_result, request, response)
Expand Down
2 changes: 1 addition & 1 deletion openapi_core/contrib/falcon/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from falcon import status_codes
from falcon.constants import MEDIA_JSON

from openapi_core.exceptions import MissingRequiredParameter
from openapi_core.templating.media_types.exceptions import MediaTypeNotFound
from openapi_core.templating.paths.exceptions import OperationNotFound
from openapi_core.templating.paths.exceptions import PathNotFound
from openapi_core.templating.paths.exceptions import ServerNotFound
from openapi_core.validation.exceptions import InvalidSecurity
from openapi_core.validation.exceptions import MissingRequiredParameter


class FalconOpenAPIErrorsHandler:
Expand Down
17 changes: 10 additions & 7 deletions openapi_core/contrib/falcon/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
from openapi_core.contrib.falcon.requests import FalconOpenAPIRequest
from openapi_core.contrib.falcon.responses import FalconOpenAPIResponse
from openapi_core.validation.processors import OpenAPIProcessor
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.validation.request import openapi_request_validator
from openapi_core.validation.response import openapi_response_validator


class FalconOpenAPIMiddleware:
Expand All @@ -16,11 +16,13 @@ class FalconOpenAPIMiddleware:

def __init__(
self,
spec,
validation_processor,
request_class=None,
response_class=None,
errors_handler=None,
):
self.spec = spec
self.validation_processor = validation_processor
self.request_class = request_class or self.request_class
self.response_class = response_class or self.response_class
Expand All @@ -34,12 +36,11 @@ def from_spec(
response_class=None,
errors_handler=None,
):
request_validator = RequestValidator(spec)
response_validator = ResponseValidator(spec)
validation_processor = OpenAPIProcessor(
request_validator, response_validator
openapi_request_validator, openapi_response_validator
)
return cls(
spec,
validation_processor,
request_class=request_class,
response_class=response_class,
Expand Down Expand Up @@ -76,9 +77,11 @@ def _get_openapi_response(self, response):
return self.response_class(response)

def _process_openapi_request(self, openapi_request):
return self.validation_processor.process_request(openapi_request)
return self.validation_processor.process_request(
self.spec, openapi_request
)

def _process_openapi_response(self, opneapi_request, openapi_response):
return self.validation_processor.process_response(
opneapi_request, openapi_response
self.spec, opneapi_request, openapi_response
)
13 changes: 7 additions & 6 deletions openapi_core/contrib/flask/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
from openapi_core.contrib.flask.requests import FlaskOpenAPIRequest
from openapi_core.contrib.flask.responses import FlaskOpenAPIResponse
from openapi_core.validation.decorators import OpenAPIDecorator
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.validation.request import openapi_request_validator
from openapi_core.validation.response import openapi_response_validator


class FlaskOpenAPIViewDecorator(OpenAPIDecorator):
def __init__(
self,
spec,
request_validator,
response_validator,
request_class=FlaskOpenAPIRequest,
Expand All @@ -19,6 +20,7 @@ def __init__(
openapi_errors_handler=FlaskOpenAPIErrorsHandler,
):
super().__init__(
spec,
request_validator,
response_validator,
request_class,
Expand All @@ -43,11 +45,10 @@ def from_spec(
request_provider=FlaskRequestProvider,
openapi_errors_handler=FlaskOpenAPIErrorsHandler,
):
request_validator = RequestValidator(spec)
response_validator = ResponseValidator(spec)
return cls(
request_validator=request_validator,
response_validator=response_validator,
spec,
request_validator=openapi_request_validator,
response_validator=openapi_response_validator,
request_class=request_class,
response_class=response_class,
request_provider=request_provider,
Expand Down
12 changes: 6 additions & 6 deletions openapi_core/contrib/flask/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator
from openapi_core.contrib.flask.handlers import FlaskOpenAPIErrorsHandler
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.validation.response.validators import ResponseValidator
from openapi_core.validation.request import openapi_request_validator
from openapi_core.validation.response import openapi_response_validator


class FlaskOpenAPIView(MethodView):
Expand All @@ -14,13 +14,13 @@ class FlaskOpenAPIView(MethodView):

def __init__(self, spec):
super().__init__()
self.request_validator = RequestValidator(spec)
self.response_validator = ResponseValidator(spec)
self.spec = spec

def dispatch_request(self, *args, **kwargs):
decorator = FlaskOpenAPIViewDecorator(
request_validator=self.request_validator,
response_validator=self.response_validator,
self.spec,
request_validator=openapi_request_validator,
response_validator=openapi_response_validator,
openapi_errors_handler=self.openapi_errors_handler,
)
return decorator(super().dispatch_request)(*args, **kwargs)
88 changes: 0 additions & 88 deletions openapi_core/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,93 +1,5 @@
"""OpenAPI core exceptions module"""
from dataclasses import dataclass

from openapi_core.validation.request.protocols import Request
from openapi_core.validation.response.protocols import Response


class OpenAPIError(Exception):
pass


class OpenAPIHeaderError(OpenAPIError):
pass


class MissingHeaderError(OpenAPIHeaderError):
"""Missing header error"""


@dataclass
class MissingHeader(MissingHeaderError):
name: str

def __str__(self):
return f"Missing header (without default value): {self.name}"


@dataclass
class MissingRequiredHeader(MissingHeaderError):
name: str

def __str__(self):
return f"Missing required header: {self.name}"


class OpenAPIParameterError(OpenAPIError):
pass


class MissingParameterError(OpenAPIParameterError):
"""Missing parameter error"""


@dataclass
class MissingParameter(MissingParameterError):
name: str

def __str__(self):
return f"Missing parameter (without default value): {self.name}"


@dataclass
class MissingRequiredParameter(MissingParameterError):
name: str

def __str__(self):
return f"Missing required parameter: {self.name}"


class OpenAPIRequestBodyError(OpenAPIError):
pass


class MissingRequestBodyError(OpenAPIRequestBodyError):
"""Missing request body error"""


@dataclass
class MissingRequestBody(MissingRequestBodyError):
request: Request

def __str__(self):
return "Missing request body"


@dataclass
class MissingRequiredRequestBody(MissingRequestBodyError):
request: Request

def __str__(self):
return "Missing required request body"


class OpenAPIResponseError(OpenAPIError):
pass


@dataclass
class MissingResponseContent(OpenAPIResponseError):
response: Response

def __str__(self):
return "Missing response content"
20 changes: 20 additions & 0 deletions openapi_core/validation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""OpenAPI core validation module"""
from openapi_core.validation.request import openapi_request_body_validator
from openapi_core.validation.request import (
openapi_request_parameters_validator,
)
from openapi_core.validation.request import openapi_request_security_validator
from openapi_core.validation.request import openapi_request_validator
from openapi_core.validation.response import openapi_response_data_validator
from openapi_core.validation.response import openapi_response_headers_validator
from openapi_core.validation.response import openapi_response_validator

__all__ = [
"openapi_request_body_validator",
"openapi_request_parameters_validator",
"openapi_request_security_validator",
"openapi_request_validator",
"openapi_response_data_validator",
"openapi_response_headers_validator",
"openapi_response_validator",
]
6 changes: 4 additions & 2 deletions openapi_core/validation/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class OpenAPIDecorator(OpenAPIProcessor):
def __init__(
self,
spec,
request_validator,
response_validator,
request_class,
Expand All @@ -15,6 +16,7 @@ def __init__(
openapi_errors_handler,
):
super().__init__(request_validator, response_validator)
self.spec = spec
self.request_class = request_class
self.response_class = response_class
self.request_provider = request_provider
Expand All @@ -25,15 +27,15 @@ def __call__(self, view):
def decorated(*args, **kwargs):
request = self._get_request(*args, **kwargs)
openapi_request = self._get_openapi_request(request)
request_result = self.process_request(openapi_request)
request_result = self.process_request(self.spec, openapi_request)
if request_result.errors:
return self._handle_request_errors(request_result)
response = self._handle_request_view(
request_result, view, *args, **kwargs
)
openapi_response = self._get_openapi_response(response)
response_result = self.process_response(
openapi_request, openapi_response
self.spec, openapi_request, openapi_response
)
if response_result.errors:
return self._handle_response_errors(response_result)
Expand Down
Loading