Browse Source

Rewrite redirects for ember-cli

Rafał Pitoń 10 years ago
parent
commit
2a224ea795

+ 6 - 0
docs/developers/settings.rst

@@ -241,6 +241,12 @@ MISAGO_DYNAMIC_AVATAR_DRAWER
 Function used to create unique avatar for this user. Allows for customization of algorithm used to generate those.
 
 
+MISAGO_EMBER_CLI_ORIGIN
+-----------------------
+
+Local address under which Ember-CLI web server is being ran. Used for rewriting redirects in development using Ember-CLI (``DEBUG = True``). Defaults to `http://localhost:4200`. Set this to empty string or ``False`` to disable this feature completely.
+
+
 MISAGO_FRESH_CONTENT_PERIOD
 ---------------------------
 Controls amount of data used in building "New threads" and "Threads with unread replies" lists. Active forums can try lowering this value while less active ones may wish to increase this number.

+ 7 - 0
misago/conf/defaults.py

@@ -118,6 +118,7 @@ INSTALLED_APPS = (
 )
 
 MIDDLEWARE_CLASSES = (
+    'misago.core.middleware.embercliredirects.EmberCLIRedirectsMiddleware',
     'misago.users.middleware.AvatarServerMiddleware',
     'misago.users.middleware.RealIPMiddleware',
     'misago.core.middleware.preloademberdata.PreloadEmberDataMiddleware',
@@ -346,6 +347,12 @@ MISAGO_SENDFILE_LOCATIONS_PATH = ''
 CRISPY_TEMPLATE_PACK = 'bootstrap3'
 
 
+# Ember-CLI dev server address, used in rewriting redirects in dev
+# If you are using different port to run Ember-CLI dev server,
+# override this setting in your settings.py.
+MISAGO_EMBER_CLI_ORIGIN = 'http://localhost:4200'
+
+
 # Rest Framework Configuration
 REST_FRAMEWORK = {
     'EXCEPTION_HANDLER': 'misago.core.exceptionhandler.handle_api_exception'

+ 37 - 0
misago/core/middleware/embercliredirects.py

@@ -0,0 +1,37 @@
+from django.conf import settings
+
+
+class EmberCLIRedirectsMiddleware(object):
+    """
+    Utility middleware for development
+
+    Redirects returned by Django point to dev server's port,
+    thus pulling us out from Ember's dev server.
+
+    This middleware detects requests coming from Ember and makes redirects
+    point back to it instead.
+
+    This middleware works only in DEBUG and requires browser to send Origin
+    header that matches one in MISAGO_EMBER_CLI_ORIGIN setting.
+    """
+    def process_response(self, request, response):
+        if settings.DEBUG and settings.MISAGO_EMBER_CLI_ORIGIN:
+            rewrite_ember_cli_redirect_url = (
+                response.status_code in (301, 302)
+                and request.META.get('HTTP_ORIGIN')
+                and self.is_ember_cli_request(request)
+            )
+
+            if rewrite_ember_cli_redirect_url:
+                return self.rewrite_http_redirect_url(response)
+
+        return response
+
+    def is_ember_cli_request(self, request):
+        http_origin = request.META.get('HTTP_ORIGIN', '')
+        return http_origin.endswith(settings.MISAGO_EMBER_CLI_ORIGIN)
+
+    def rewrite_http_redirect_url(self, response):
+        final_location = settings.MISAGO_EMBER_CLI_ORIGIN, response['location']
+        response['location'] = ''.join(final_location)
+        return response

+ 78 - 0
misago/core/tests/test_embercliredirects_middleware.py

@@ -0,0 +1,78 @@
+from django.conf import settings
+from django.test import TestCase
+
+from misago.core.middleware.embercliredirects import (
+    EmberCLIRedirectsMiddleware)
+
+
+class MockRequest(object):
+    def __init__(self, origin):
+        self.META = {'HTTP_ORIGIN': origin}
+
+
+class MockResponse(object):
+    def __init__(self, location, code=301):
+        self.status_code = code
+        self._dict = {'location': location}
+
+    def __setitem__(self, key, item):
+        self._dict[key] = item
+
+    def __getitem__(self, key):
+        return self._dict[key]
+
+
+class EmberCLIRedirectsMiddlewareTests(TestCase):
+    def test_process_response_rewrites_redirect(self):
+        """process_response rewrites redirect"""
+        middleware = EmberCLIRedirectsMiddleware()
+
+        request = MockRequest(settings.MISAGO_EMBER_CLI_ORIGIN)
+
+        url = '/thread/bob-boberson-rules-1/'
+        response = MockResponse(url, 301)
+
+        with self.settings(DEBUG=True):
+            response = MockResponse(url, 301)
+
+            middleware.process_response(request, response)
+            self.assertTrue(response['location'].startswith(
+                settings.MISAGO_EMBER_CLI_ORIGIN))
+            self.assertTrue(response['location'].endswith(url))
+
+        with self.settings(DEBUG=False):
+            response = MockResponse(url, 301)
+
+            middleware.process_response(request, response)
+            self.assertFalse(response['location'].startswith(
+                settings.MISAGO_EMBER_CLI_ORIGIN))
+            self.assertTrue(response['location'].endswith(url))
+
+        with self.settings(MISAGO_EMBER_CLI_ORIGIN=''):
+            response = MockResponse(url, 301)
+
+            middleware.process_response(request, response)
+            self.assertFalse(response['location'].startswith(
+                settings.MISAGO_EMBER_CLI_ORIGIN))
+            self.assertTrue(response['location'].endswith(url))
+
+    def test_is_ember_cli_request(self):
+        """is_ember_cli_request test works"""
+        middleware = EmberCLIRedirectsMiddleware()
+
+        valid_request = MockRequest(settings.MISAGO_EMBER_CLI_ORIGIN)
+        self.assertTrue(middleware.is_ember_cli_request(valid_request))
+
+        invalid_request = MockRequest('http://somewhere.com/some_page.html')
+        self.assertFalse(middleware.is_ember_cli_request(invalid_request))
+
+    def rewrite_http_redirect_url(self):
+        """rewrite_http_redirect_url prepents CLI host to URL"""
+        middleware = EmberCLIRedirectsMiddleware()
+
+        url = '/thread/bob-boberson-rules-1/'
+        rewrited_url = middleware.rewrite_http_redirect_url(url)
+
+        self.assertTrue(rewrited_url.startswith(
+            settings.MISAGO_EMBER_CLI_ORIGIN))
+        self.assertTrue(rewrited_url.endswith(url))