catch errors in wsgi.Middleware.

- Catch errors in wsgi.Middleware like done in wsgi.Applications.
- Add tests for test_middleware.
- Fixes bug 1128379.

Change-Id: I2e95595c392631aebf2682d4506e4dde78cd6d69
This commit is contained in:
Chmouel Boudjnah 2013-02-18 11:46:15 +01:00
parent 9ec12e2e54
commit 0b4ee31f0f
2 changed files with 82 additions and 15 deletions

View File

@ -347,11 +347,21 @@ class Middleware(Application):
@webob.dec.wsgify(RequestClass=Request) @webob.dec.wsgify(RequestClass=Request)
def __call__(self, request): def __call__(self, request):
response = self.process_request(request) try:
if response: response = self.process_request(request)
return response if response:
response = request.get_response(self.application) return response
return self.process_response(request, response) response = request.get_response(self.application)
return self.process_response(request, response)
except exception.Error as e:
LOG.warning(e)
return render_exception(e)
except TypeError as e:
LOG.exception(e)
return render_exception(exception.ValidationError(e))
except Exception as e:
LOG.exception(e)
return render_exception(exception.UnexpectedError(exception=e))
class Debug(Middleware): class Debug(Middleware):

View File

@ -19,33 +19,38 @@ import webob
from keystone.common import wsgi from keystone.common import wsgi
from keystone.openstack.common import jsonutils from keystone.openstack.common import jsonutils
from keystone import test from keystone import test
from keystone import exception
class ApplicationTest(test.TestCase): class FakeApp(wsgi.Application):
def index(self, context):
return {'a': 'b'}
class BaseWSGITest(test.TestCase):
def setUp(self):
self.app = FakeApp()
super(BaseWSGITest, self).setUp()
def _make_request(self, url='/'): def _make_request(self, url='/'):
req = webob.Request.blank(url) req = webob.Request.blank(url)
args = {'action': 'index', 'controller': None} args = {'action': 'index', 'controller': None}
req.environ['wsgiorg.routing_args'] = [None, args] req.environ['wsgiorg.routing_args'] = [None, args]
return req return req
def test_response_content_type(self):
class FakeApp(wsgi.Application):
def index(self, context):
return {'a': 'b'}
app = FakeApp() class ApplicationTest(BaseWSGITest):
def test_response_content_type(self):
req = self._make_request() req = self._make_request()
resp = req.get_response(app) resp = req.get_response(self.app)
self.assertEqual(resp.content_type, 'application/json') self.assertEqual(resp.content_type, 'application/json')
def test_query_string_available(self): def test_query_string_available(self):
class FakeApp(wsgi.Application): class FakeApp(wsgi.Application):
def index(self, context): def index(self, context):
return context['query_string'] return context['query_string']
app = FakeApp()
req = self._make_request(url='/?1=2') req = self._make_request(url='/?1=2')
resp = req.get_response(app) resp = req.get_response(FakeApp())
self.assertEqual(jsonutils.loads(resp.body), {'1': '2'}) self.assertEqual(jsonutils.loads(resp.body), {'1': '2'})
def test_render_response(self): def test_render_response(self):
@ -76,3 +81,55 @@ class ApplicationTest(test.TestCase):
self.assertEqual(resp.body, '') self.assertEqual(resp.body, '')
self.assertEqual(resp.headers.get('Content-Length'), '0') self.assertEqual(resp.headers.get('Content-Length'), '0')
self.assertEqual(resp.headers.get('Content-Type'), None) self.assertEqual(resp.headers.get('Content-Type'), None)
class MiddlewareTest(BaseWSGITest):
def test_middleware_request(self):
class FakeMiddleware(wsgi.Middleware):
def process_request(self, req):
req.environ['fake_request'] = True
return req
req = self._make_request()
resp = FakeMiddleware(None)(req)
self.assertIn('fake_request', resp.environ)
def test_middleware_response(self):
class FakeMiddleware(wsgi.Middleware):
def process_response(self, request, response):
response.environ = {}
response.environ['fake_response'] = True
return response
req = self._make_request()
resp = FakeMiddleware(self.app)(req)
self.assertIn('fake_response', resp.environ)
def test_middleware_bad_request(self):
class FakeMiddleware(wsgi.Middleware):
def process_response(self, request, response):
raise exception.Unauthorized()
req = self._make_request()
req.environ['REMOTE_ADDR'] = '127.0.0.1'
resp = FakeMiddleware(self.app)(req)
self.assertEquals(resp.status_int, exception.Unauthorized.code)
def test_middleware_type_error(self):
class FakeMiddleware(wsgi.Middleware):
def process_response(self, request, response):
raise TypeError()
req = self._make_request()
req.environ['REMOTE_ADDR'] = '127.0.0.1'
resp = FakeMiddleware(self.app)(req)
# This is a validationerror type
self.assertEquals(resp.status_int, exception.ValidationError.code)
def test_middleware_exception_error(self):
class FakeMiddleware(wsgi.Middleware):
def process_response(self, request, response):
raise exception.UnexpectedError("EXCEPTIONERROR")
req = self._make_request()
resp = FakeMiddleware(self.app)(req)
self.assertEquals(resp.status_int, exception.UnexpectedError.code)
self.assertIn("EXCEPTIONERROR", resp.body)