Improve validator error handling
parent
c225f66fb7
commit
57d77cc48a
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue