Merge "Added ValidationErrorMiddleware"
This commit is contained in:
commit
82fae73bcd
@ -26,6 +26,7 @@ from oslo_utils import strutils
|
|||||||
from designate import exceptions
|
from designate import exceptions
|
||||||
from designate import notifications
|
from designate import notifications
|
||||||
from designate import context
|
from designate import context
|
||||||
|
from designate import objects
|
||||||
from designate.i18n import _LI
|
from designate.i18n import _LI
|
||||||
from designate.i18n import _LW
|
from designate.i18n import _LW
|
||||||
from designate.i18n import _LE
|
from designate.i18n import _LE
|
||||||
@ -268,3 +269,66 @@ class FaultWrapperMiddleware(base.Middleware):
|
|||||||
|
|
||||||
return flask.Response(status=status, headers=headers,
|
return flask.Response(status=status, headers=headers,
|
||||||
response=json.dumps(response))
|
response=json.dumps(response))
|
||||||
|
|
||||||
|
|
||||||
|
class ValidationErrorMiddleware(base.Middleware):
|
||||||
|
|
||||||
|
def __init__(self, application):
|
||||||
|
super(ValidationErrorMiddleware, self).__init__(application)
|
||||||
|
|
||||||
|
LOG.info(_LI('Starting designate validation middleware'))
|
||||||
|
|
||||||
|
@webob.dec.wsgify
|
||||||
|
def __call__(self, request):
|
||||||
|
try:
|
||||||
|
return request.get_response(self.application)
|
||||||
|
except exceptions.InvalidObject as e:
|
||||||
|
# Allow current views validation to pass through to FaultWapper
|
||||||
|
if not isinstance(e.errors, objects.ValidationErrorList):
|
||||||
|
raise
|
||||||
|
return self._handle_errors(request, e)
|
||||||
|
|
||||||
|
def _handle_errors(self, request, exception):
|
||||||
|
|
||||||
|
response = {}
|
||||||
|
|
||||||
|
headers = [
|
||||||
|
('Content-Type', 'application/json'),
|
||||||
|
]
|
||||||
|
|
||||||
|
url = getattr(request, 'url', None)
|
||||||
|
|
||||||
|
response['code'] = exception.error_code
|
||||||
|
|
||||||
|
response['type'] = exception.error_type or 'unknown'
|
||||||
|
|
||||||
|
response['errors'] = list()
|
||||||
|
|
||||||
|
for error in exception.errors:
|
||||||
|
response['errors'].append(error.to_dict())
|
||||||
|
|
||||||
|
# Return the new response
|
||||||
|
if 'context' in request.environ:
|
||||||
|
response['request_id'] = request.environ['context'].request_id
|
||||||
|
|
||||||
|
notifications.send_api_fault(request.environ['context'], url,
|
||||||
|
response['code'], exception)
|
||||||
|
else:
|
||||||
|
# TODO(ekarlso): Remove after verifying that there's actually a
|
||||||
|
# context always set
|
||||||
|
LOG.error(_LE('Missing context in request, please check.'))
|
||||||
|
|
||||||
|
return flask.Response(status=exception.error_code, headers=headers,
|
||||||
|
response=json.dumps(response))
|
||||||
|
|
||||||
|
|
||||||
|
class APIv1ValidationErrorMiddleware(ValidationErrorMiddleware):
|
||||||
|
def __init__(self, application):
|
||||||
|
super(APIv1ValidationErrorMiddleware, self).__init__(application)
|
||||||
|
self.api_version = 'API_v1'
|
||||||
|
|
||||||
|
|
||||||
|
class APIv2ValidationErrorMiddleware(ValidationErrorMiddleware):
|
||||||
|
def __init__(self, application):
|
||||||
|
super(APIv2ValidationErrorMiddleware, self).__init__(application)
|
||||||
|
self.api_version = 'API_v2'
|
||||||
|
@ -30,8 +30,8 @@ class ValidationError(base.DesignateObject):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
e = cls()
|
e = cls()
|
||||||
e.relative_path = ".".join([str(x) for x in js_error.relative_path])
|
e.relative_path = js_error.relative_path
|
||||||
e.absolute_path = ".".join([str(x) for x in js_error.absolute_path])
|
e.absolute_path = js_error.absolute_path
|
||||||
e.message = js_error.message
|
e.message = js_error.message
|
||||||
e.validator = js_error.validator
|
e.validator = js_error.validator
|
||||||
e.validator_value = js_error.validator_value
|
e.validator_value = js_error.validator_value
|
||||||
|
@ -42,6 +42,10 @@ class ApiV1Test(ApiTestCase):
|
|||||||
self.app.wsgi_app = middleware.FaultWrapperMiddleware(
|
self.app.wsgi_app = middleware.FaultWrapperMiddleware(
|
||||||
self.app.wsgi_app)
|
self.app.wsgi_app)
|
||||||
|
|
||||||
|
# Inject the ValidationError middleware
|
||||||
|
self.app.wsgi_app = middleware.APIv1ValidationErrorMiddleware(
|
||||||
|
self.app.wsgi_app)
|
||||||
|
|
||||||
# Inject the TestAuth middleware
|
# Inject the TestAuth middleware
|
||||||
self.app.wsgi_app = middleware.TestContextMiddleware(
|
self.app.wsgi_app = middleware.TestContextMiddleware(
|
||||||
self.app.wsgi_app, self.admin_context.tenant,
|
self.app.wsgi_app, self.admin_context.tenant,
|
||||||
|
@ -49,6 +49,9 @@ class ApiV2TestCase(ApiTestCase):
|
|||||||
# Inject the FaultWrapper middleware
|
# Inject the FaultWrapper middleware
|
||||||
self.app = middleware.FaultWrapperMiddleware(self.app)
|
self.app = middleware.FaultWrapperMiddleware(self.app)
|
||||||
|
|
||||||
|
# Inject the ValidationError middleware
|
||||||
|
self.app = middleware.APIv2ValidationErrorMiddleware(self.app)
|
||||||
|
|
||||||
# Inject the TestContext middleware
|
# Inject the TestContext middleware
|
||||||
self.app = middleware.TestContextMiddleware(
|
self.app = middleware.TestContextMiddleware(
|
||||||
self.app, self.admin_context.tenant,
|
self.app, self.admin_context.tenant,
|
||||||
|
@ -381,8 +381,9 @@ class DesignateObjectTest(tests.TestCase):
|
|||||||
self.assertEqual('format', error.validator)
|
self.assertEqual('format', error.validator)
|
||||||
|
|
||||||
# Ensure the nested ID field has triggered the failure.
|
# Ensure the nested ID field has triggered the failure.
|
||||||
self.assertEqual('nested.id', error.absolute_path)
|
# For some reason testtools turns lists into deques :/
|
||||||
self.assertEqual('nested.id', error.relative_path)
|
self.assertEqual(list(error.absolute_path), ['nested', 'id'])
|
||||||
|
self.assertEqual(list(error.relative_path), ['nested', 'id'])
|
||||||
|
|
||||||
# Set the Nested ID field to a valid value
|
# Set the Nested ID field to a valid value
|
||||||
obj.nested.id = 'ffded5c4-e4f6-4e02-a175-48e13c5c12a0'
|
obj.nested.id = 'ffded5c4-e4f6-4e02-a175-48e13c5c12a0'
|
||||||
|
@ -9,16 +9,16 @@ paste.app_factory = designate.api.versions:factory
|
|||||||
|
|
||||||
[composite:osapi_dns_v1]
|
[composite:osapi_dns_v1]
|
||||||
use = call:designate.api.middleware:auth_pipeline_factory
|
use = call:designate.api.middleware:auth_pipeline_factory
|
||||||
noauth = request_id noauthcontext maintenance faultwrapper normalizeuri osapi_dns_app_v1
|
noauth = request_id noauthcontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
|
||||||
keystone = request_id authtoken keystonecontext maintenance faultwrapper normalizeuri osapi_dns_app_v1
|
keystone = request_id authtoken keystonecontext maintenance validation_API_v1 faultwrapper normalizeuri osapi_dns_app_v1
|
||||||
|
|
||||||
[app:osapi_dns_app_v1]
|
[app:osapi_dns_app_v1]
|
||||||
paste.app_factory = designate.api.v1:factory
|
paste.app_factory = designate.api.v1:factory
|
||||||
|
|
||||||
[composite:osapi_dns_v2]
|
[composite:osapi_dns_v2]
|
||||||
use = call:designate.api.middleware:auth_pipeline_factory
|
use = call:designate.api.middleware:auth_pipeline_factory
|
||||||
noauth = request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_v2
|
noauth = request_id faultwrapper validation_API_v2 noauthcontext maintenance normalizeuri osapi_dns_app_v2
|
||||||
keystone = request_id faultwrapper authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
|
keystone = request_id faultwrapper validation_API_v2 authtoken keystonecontext maintenance normalizeuri osapi_dns_app_v2
|
||||||
|
|
||||||
[app:osapi_dns_app_v2]
|
[app:osapi_dns_app_v2]
|
||||||
paste.app_factory = designate.api.v2:factory
|
paste.app_factory = designate.api.v2:factory
|
||||||
@ -43,3 +43,9 @@ paste.filter_factory = designate.api.middleware:NormalizeURIMiddleware.factory
|
|||||||
|
|
||||||
[filter:faultwrapper]
|
[filter:faultwrapper]
|
||||||
paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory
|
paste.filter_factory = designate.api.middleware:FaultWrapperMiddleware.factory
|
||||||
|
|
||||||
|
[filter:validation_API_v1]
|
||||||
|
paste.filter_factory = designate.api.middleware:APIv1ValidationErrorMiddleware.factory
|
||||||
|
|
||||||
|
[filter:validation_API_v2]
|
||||||
|
paste.filter_factory = designate.api.middleware:APIv2ValidationErrorMiddleware.factory
|
||||||
|
Loading…
Reference in New Issue
Block a user