From 0b4ee31f0f71d62c4955847ec775dc0541e5a2c6 Mon Sep 17 00:00:00 2001 From: Chmouel Boudjnah Date: Mon, 18 Feb 2013 11:46:15 +0100 Subject: [PATCH] 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 --- keystone/common/wsgi.py | 20 ++++++++--- tests/test_wsgi.py | 77 +++++++++++++++++++++++++++++++++++------ 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py index 4c9a90bf4d..72133f4098 100644 --- a/keystone/common/wsgi.py +++ b/keystone/common/wsgi.py @@ -347,11 +347,21 @@ class Middleware(Application): @webob.dec.wsgify(RequestClass=Request) def __call__(self, request): - response = self.process_request(request) - if response: - return response - response = request.get_response(self.application) - return self.process_response(request, response) + try: + response = self.process_request(request) + if response: + return 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): diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py index 3c9eb2af15..9bc2601727 100644 --- a/tests/test_wsgi.py +++ b/tests/test_wsgi.py @@ -19,33 +19,38 @@ import webob from keystone.common import wsgi from keystone.openstack.common import jsonutils 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='/'): req = webob.Request.blank(url) args = {'action': 'index', 'controller': None} req.environ['wsgiorg.routing_args'] = [None, args] 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() - resp = req.get_response(app) + resp = req.get_response(self.app) self.assertEqual(resp.content_type, 'application/json') def test_query_string_available(self): class FakeApp(wsgi.Application): def index(self, context): return context['query_string'] - - app = FakeApp() 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'}) def test_render_response(self): @@ -76,3 +81,55 @@ class ApplicationTest(test.TestCase): self.assertEqual(resp.body, '') self.assertEqual(resp.headers.get('Content-Length'), '0') 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)