diff --git a/horizon/middleware/base.py b/horizon/middleware/base.py index aa67c29042..3b39531ebd 100644 --- a/horizon/middleware/base.py +++ b/horizon/middleware/base.py @@ -43,6 +43,15 @@ class HorizonMiddleware(object): logout_reason = None + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + self.process_request(request) + response = self.get_response(request) + response = self.process_response(request, response) + return response + def process_request(self, request): """Adds data necessary for Horizon to function to the request.""" diff --git a/horizon/middleware/operation_log.py b/horizon/middleware/operation_log.py index a1673b83d1..55e8e914fd 100644 --- a/horizon/middleware/operation_log.py +++ b/horizon/middleware/operation_log.py @@ -52,10 +52,12 @@ class OperationLogMiddleware(object): # In order to allow to access from mock in test cases. return self._logger - def __init__(self): + def __init__(self, get_response): if not getattr(settings, "OPERATION_LOG_ENABLED", False): raise MiddlewareNotUsed + self.get_response = get_response + # set configurations _log_option = getattr(settings, "OPERATION_LOG_OPTIONS", {}) _available_methods = ['POST', 'GET', 'PUT', 'DELETE'] @@ -77,6 +79,11 @@ class OperationLogMiddleware(object): ignored_urls = _log_option.get("ignore_urls", _default_ignored_urls) self._ignored_urls = [re.compile(url) for url in ignored_urls] + def __call__(self, request): + response = self.get_response(request) + response = self.process_response(request, response) + return response + def process_response(self, request, response): """Log user operation.""" log_format = self._get_log_format(request) diff --git a/horizon/test/helpers.py b/horizon/test/helpers.py index d954e63982..06f5fcdb3d 100644 --- a/horizon/test/helpers.py +++ b/horizon/test/helpers.py @@ -141,8 +141,12 @@ class TestCase(django_test.TestCase): self._setup_factory() self._setup_user() self._setup_request() - middleware.HorizonMiddleware().process_request(self.request) - AuthenticationMiddleware().process_request(self.request) + # A dummy get_response function (which is not callable) is passed + # because middlewares below are used only to populate request attrs. + middleware.HorizonMiddleware('dummy_get_response') \ + .process_request(self.request) + AuthenticationMiddleware('dummy_get_response') \ + .process_request(self.request) os.environ["HORIZON_TEST_RUN"] = "True" def _setup_test_data(self): diff --git a/horizon/test/settings.py b/horizon/test/settings.py index 3952d73ac6..0f9980abf7 100644 --- a/horizon/test/settings.py +++ b/horizon/test/settings.py @@ -62,7 +62,7 @@ INSTALLED_APPS = ( 'openstack_auth' ) -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', diff --git a/horizon/test/unit/middleware/test_base.py b/horizon/test/unit/middleware/test_base.py index 6e60272e08..78db68d2e5 100644 --- a/horizon/test/unit/middleware/test_base.py +++ b/horizon/test/unit/middleware/test_base.py @@ -13,9 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. -import django +import mock + from django.conf import settings from django.http import HttpResponseRedirect +from django import test as django_test from django.utils import timezone from horizon import exceptions @@ -23,32 +25,32 @@ from horizon import middleware from horizon.test import helpers as test -class MiddlewareTests(test.TestCase): +class MiddlewareTests(django_test.TestCase): def setUp(self): self._timezone_backup = timezone.get_current_timezone_name() - return super(MiddlewareTests, self).setUp() + self.factory = test.RequestFactoryWithMessages() + self.get_response = mock.Mock() + super(MiddlewareTests, self).setUp() def tearDown(self): timezone.activate(self._timezone_backup) - return super(MiddlewareTests, self).tearDown() + super(MiddlewareTests, self).tearDown() def test_redirect_login_fail_to_login(self): url = settings.LOGIN_URL request = self.factory.post(url) + self.get_response.return_value = request - mw = middleware.HorizonMiddleware() + mw = middleware.HorizonMiddleware(self.get_response) resp = mw.process_exception(request, exceptions.NotAuthenticated()) resp.client = self.client - if django.VERSION >= (1, 9): - self.assertRedirects(resp, settings.TESTSERVER + url) - else: - self.assertRedirects(resp, url) + self.assertRedirects(resp, settings.TESTSERVER + url) def test_process_response_redirect_on_ajax_request(self): url = settings.LOGIN_URL - mw = middleware.HorizonMiddleware() + mw = middleware.HorizonMiddleware(self.get_response) request = self.factory.post(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') @@ -65,7 +67,7 @@ class MiddlewareTests(test.TestCase): def test_timezone_awareness(self): url = settings.LOGIN_REDIRECT_URL - mw = middleware.HorizonMiddleware() + mw = middleware.HorizonMiddleware(self.get_response) request = self.factory.get(url) request.session['django_timezone'] = 'America/Chicago' diff --git a/horizon/test/unit/middleware/test_operation_log.py b/horizon/test/unit/middleware/test_operation_log.py index 1f6af561a1..daf0ef251f 100644 --- a/horizon/test/unit/middleware/test_operation_log.py +++ b/horizon/test/unit/middleware/test_operation_log.py @@ -12,25 +12,34 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + +import mock from mock import patch from django.conf import settings from django.core.exceptions import MiddlewareNotUsed from django.http import HttpResponseRedirect +from django import test as django_test from django.test.utils import override_settings from horizon import middleware from horizon.test import helpers as test -class OperationLogMiddlewareTest(test.TestCase): +class OperationLogMiddlewareTest(django_test.TestCase): http_host = u'test_host' http_referer = u'/dashboard/test_http_referer' + def setUp(self): + super(OperationLogMiddlewareTest, self).setUp() + self.factory = test.RequestFactoryWithMessages() + def test_middleware_not_used(self): + get_response = mock.Mock() with self.assertRaises(MiddlewareNotUsed): - middleware.OperationLogMiddleware() + middleware.OperationLogMiddleware(get_response) + self.assertFalse(get_response.called) def _test_ready_for_post(self): url = settings.LOGIN_URL @@ -63,11 +72,13 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_process_response_for_post(self, mock_logger): - olm = middleware.OperationLogMiddleware() request, response = self._test_ready_for_post() + get_response = mock.Mock(return_value=response) + olm = middleware.OperationLogMiddleware(get_response) - resp = olm.process_response(request, response) + resp = olm(request) + get_response.assert_called_once_with(request) self.assertTrue(mock_logger.info.called) self.assertEqual(302, resp.status_code) log_args = mock_logger.info.call_args[0] @@ -86,11 +97,13 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_process_response_for_get(self, mock_logger): - olm = middleware.OperationLogMiddleware() request, response = self._test_ready_for_get() + get_response = mock.Mock(return_value=response) + olm = middleware.OperationLogMiddleware(get_response) - resp = olm.process_response(request, response) + resp = olm(request) + get_response.assert_called_once_with(request) self.assertTrue(mock_logger.info.called) self.assertEqual(302, resp.status_code) log_args = mock_logger.info.call_args[0] @@ -106,11 +119,13 @@ class OperationLogMiddlewareTest(test.TestCase): 'OPERATION_LOG')) def test_process_response_for_get_no_target(self, mock_logger): """In default setting, Get method is not logged""" - olm = middleware.OperationLogMiddleware() request, response = self._test_ready_for_get() + get_response = mock.Mock(return_value=response) + olm = middleware.OperationLogMiddleware(get_response) - resp = olm.process_response(request, response) + resp = olm(request) + get_response.assert_called_once_with(request) self.assertEqual(0, mock_logger.info.call_count) self.assertEqual(302, resp.status_code) @@ -118,12 +133,14 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_process_exception(self, mock_logger): - olm = middleware.OperationLogMiddleware() request, response = self._test_ready_for_post() + get_response = mock.Mock(return_value=response) + olm = middleware.OperationLogMiddleware(get_response) exception = Exception("Unexpected error occurred.") olm.process_exception(request, exception) + self.assertFalse(get_response.called) log_args = mock_logger.info.call_args[0] logging_str = log_args[0] % log_args[1] self.assertTrue(mock_logger.info.called) @@ -140,7 +157,8 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_get_log_format(self, mock_logger): - olm = middleware.OperationLogMiddleware() + get_response = mock.Mock() + olm = middleware.OperationLogMiddleware(get_response) request, _ = self._test_ready_for_get() self.assertEqual(olm._default_format, olm._get_log_format(request)) @@ -149,7 +167,8 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_get_log_format_no_user(self, mock_logger): - olm = middleware.OperationLogMiddleware() + get_response = mock.Mock() + olm = middleware.OperationLogMiddleware(get_response) request, _ = self._test_ready_for_get() delattr(request, "user") @@ -159,7 +178,8 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_get_log_format_unknown_method(self, mock_logger): - olm = middleware.OperationLogMiddleware() + get_response = mock.Mock() + olm = middleware.OperationLogMiddleware(get_response) request, _ = self._test_ready_for_get() request.method = "FAKE" @@ -169,7 +189,8 @@ class OperationLogMiddlewareTest(test.TestCase): @patch(('horizon.middleware.operation_log.OperationLogMiddleware.' 'OPERATION_LOG')) def test_get_log_format_ignored_url(self, mock_logger): - olm = middleware.OperationLogMiddleware() + get_response = mock.Mock() + olm = middleware.OperationLogMiddleware(get_response) request, _ = self._test_ready_for_get("/api/policy") self.assertIsNone(olm._get_log_format(request)) diff --git a/horizon/test/unit/tabs/test_tabs.py b/horizon/test/unit/tabs/test_tabs.py index 91a3421b15..235674011d 100644 --- a/horizon/test/unit/tabs/test_tabs.py +++ b/horizon/test/unit/tabs/test_tabs.py @@ -335,7 +335,7 @@ class TabExceptionTests(test.TestCase): TabWithTableView.tab_group_class.tabs.append(RedirectExceptionTab) view = TabWithTableView.as_view() req = self.factory.get("/") - mw = middleware.HorizonMiddleware() + mw = middleware.HorizonMiddleware('dummy_get_response') try: resp = view(req) except Exception as e: diff --git a/horizon/test/unit/test_messages.py b/horizon/test/unit/test_messages.py index 50f30ae25c..bbd976d1a7 100644 --- a/horizon/test/unit/test_messages.py +++ b/horizon/test/unit/test_messages.py @@ -34,7 +34,8 @@ class MessageTests(test.TestCase): messages.error(req, string) self.assertItemsEqual(req.horizon['async_messages'], [expected]) res = http.HttpResponse() - res = middleware.HorizonMiddleware().process_response(req, res) + res = middleware.HorizonMiddleware('dummy_get_response') \ + .process_response(req, res) self.assertEqual(json.dumps([expected]), res['X-Horizon-Messages']) @@ -48,6 +49,7 @@ class MessageTests(test.TestCase): messages.error(req, string) self.assertItemsEqual(req.horizon['async_messages'], [expected]) res = http.HttpResponse() - res = middleware.HorizonMiddleware().process_response(req, res) + res = middleware.HorizonMiddleware('dummy_get_response') \ + .process_response(req, res) self.assertEqual(json.dumps([expected]), res['X-Horizon-Messages']) diff --git a/horizon/themes.py b/horizon/themes.py index ba8ad07f89..e75d07f308 100644 --- a/horizon/themes.py +++ b/horizon/themes.py @@ -99,6 +99,15 @@ class ThemeMiddleware(object): the Cookie's theme value for use later in the Django chain. """ + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + self.process_request(request) + response = self.get_response(request) + response = self.process_response(request, response) + return response + def process_request(self, request): # Determine which theme the user has configured and store in local diff --git a/openstack_auth/tests/settings.py b/openstack_auth/tests/settings.py index 93a9dcb91f..4b1a43d2b4 100644 --- a/openstack_auth/tests/settings.py +++ b/openstack_auth/tests/settings.py @@ -27,7 +27,7 @@ INSTALLED_APPS = [ 'openstack_auth.tests' ] -MIDDLEWARE_CLASSES = [ +MIDDLEWARE = [ 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', diff --git a/openstack_dashboard/contrib/developer/profiler/middleware.py b/openstack_dashboard/contrib/developer/profiler/middleware.py index 9268774cc7..91089a18c0 100644 --- a/openstack_dashboard/contrib/developer/profiler/middleware.py +++ b/openstack_dashboard/contrib/developer/profiler/middleware.py @@ -39,10 +39,16 @@ class ProfilerClientMiddleware(object): ('HTTP_X_TRACE_HMAC', 'X-Trace-HMAC') ] - def __init__(self): + def __init__(self, get_response): if not PROFILER_ENABLED: raise exceptions.MiddlewareNotUsed() super(ProfilerClientMiddleware, self).__init__() + self.get_response = get_response + + def __call__(self, request): + self.process_request(request) + response = self.get_response(request) + return response def is_async_profiling(self, request): return self.profiler_headers[0][0] in request.META @@ -62,14 +68,20 @@ class ProfilerClientMiddleware(object): class ProfilerMiddleware(object): - def __init__(self): + def __init__(self, get_response): self.name = PROFILER_CONF.get('facility_name', 'horizon') self.hmac_keys = PROFILER_CONF.get('keys', []) + self.get_response = get_response if PROFILER_ENABLED: api.init_notifier(PROFILER_CONF.get('notifier_connection_string')) else: raise exceptions.MiddlewareNotUsed() + def __call__(self, request): + response = self.get_response(request) + response = self.process_response(request, response) + return response + @staticmethod def is_authenticated(request): return hasattr(request, "user") and request.user.is_authenticated diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index 69cb0f4018..b94c47c54e 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -107,7 +107,7 @@ OPENSTACK_IMAGE_BACKEND = { ] } -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',