Improve validator error handling

openapi3
Cristi Vîjdea 2018-01-11 21:19:42 +01:00
parent c225f66fb7
commit 57d77cc48a
6 changed files with 23 additions and 15 deletions

View File

@ -126,7 +126,7 @@ In ``urls.py``:
contact=openapi.Contact(email="contact@snippets.local"),
license=openapi.License(name="BSD License"),
),
validators=['ssv', 'flex'],
validators=['flex', 'ssv'],
public=True,
permission_classes=(permissions.AllowAny,),
)
@ -267,7 +267,7 @@ caching the schema view in-memory, with some sane defaults:
Given the numerous methods to manually customzie the generated schema, it makes sense to validate the result to ensure
it still conforms to OpenAPI 2.0. To this end, validation is provided at the generation point using python swagger
libraries, and can be activated by passing :python:`validators=['ssv', 'flex']` to ``get_schema_view``; if the generated
libraries, and can be activated by passing :python:`validators=['flex', 'ssv']` to ``get_schema_view``; if the generated
schema is not valid, a :python:`SwaggerValidationError` is raised by the handling codec.
**Warning:** This internal validation can slow down your server.

View File

@ -12,22 +12,22 @@ from .app_settings import swagger_settings
from .errors import SwaggerValidationError
def _validate_flex(spec, codec):
def _validate_flex(spec):
from flex.core import parse as validate_flex
from flex.exceptions import ValidationError
try:
validate_flex(spec)
except ValidationError as ex:
raise_from(SwaggerValidationError(str(ex), 'flex', spec, codec), ex)
raise_from(SwaggerValidationError(str(ex)), ex)
def _validate_swagger_spec_validator(spec, codec):
def _validate_swagger_spec_validator(spec):
from swagger_spec_validator.validator20 import validate_spec as validate_ssv
from swagger_spec_validator.common import SwaggerValidationError as SSVErr
try:
validate_ssv(spec)
except SSVErr as ex:
raise_from(SwaggerValidationError(str(ex), 'swagger_spec_validator', spec, codec), ex)
raise_from(SwaggerValidationError(str(ex)), ex)
#:
@ -61,10 +61,17 @@ class _OpenAPICodec(object):
raise TypeError('Expected a `openapi.Swagger` instance')
spec = self.generate_swagger_object(document)
errors = {}
for validator in self.validators:
try:
# validate a deepcopy of the spec to prevent the validator from messing with it
# for example, swagger_spec_validator adds an x-scope property to all references
VALIDATORS[validator](copy.deepcopy(spec), self)
VALIDATORS[validator](copy.deepcopy(spec))
except SwaggerValidationError as e:
errors[validator] = str(e)
if errors:
raise SwaggerValidationError("spec validation failed", errors, spec, self)
return force_bytes(self._dump_dict(spec))
def encode_error(self, err):

View File

@ -3,9 +3,9 @@ class SwaggerError(Exception):
class SwaggerValidationError(SwaggerError):
def __init__(self, msg, validator_name, spec, source_codec, *args):
def __init__(self, msg, errors=None, spec=None, source_codec=None, *args):
super(SwaggerValidationError, self).__init__(msg, *args)
self.validator_name = validator_name
self.errors = errors
self.spec = spec
self.source_codec = source_codec

View File

@ -13,7 +13,7 @@ class SwaggerExceptionMiddleware(object):
def process_exception(self, request, exception):
if isinstance(exception, SwaggerValidationError):
err = {'errors': {exception.validator_name: str(exception)}}
err = {'errors': exception.errors, 'message': str(exception)}
codec = exception.source_codec
if isinstance(codec, _OpenAPICodec):
err = codec.encode_error(err)

View File

@ -9,7 +9,7 @@ from .codecs import VALIDATORS, OpenAPICodecJson, OpenAPICodecYaml
class _SpecRenderer(BaseRenderer):
"""Base class for text renderers. Handles encoding and validation."""
charset = None
validators = ['ssv', 'flex']
validators = []
codec_class = None
@classmethod

View File

@ -12,8 +12,9 @@ from rest_framework.views import APIView
from .app_settings import swagger_settings
from .generators import OpenAPISchemaGenerator
from .renderers import OpenAPIRenderer, ReDocRenderer, SwaggerJSONRenderer, SwaggerUIRenderer, SwaggerYAMLRenderer, \
ReDocAlphaRenderer
from .renderers import (
OpenAPIRenderer, ReDocAlphaRenderer, ReDocRenderer, SwaggerJSONRenderer, SwaggerUIRenderer, SwaggerYAMLRenderer
)
SPEC_RENDERERS = (SwaggerYAMLRenderer, SwaggerJSONRenderer, OpenAPIRenderer)
UI_RENDERERS = {