Code

Ticket #987: redirect_absoluteuri.2.patch

File redirect_absoluteuri.2.patch, 8.1 KB (added by SmileyChris, 7 years ago)
  • django/core/handlers/base.py

     
    33from django import http 
    44import sys 
    55 
     6class BaseCompulsaryMiddleware(object): 
     7    def process_response(self, request, response): 
     8        # Absolute URI redirects: Ensures that any redirect attempt (which uses 
     9        # the HTTP Location header) to a relative location is converted to an 
     10        # absolute URI, as required by RFC 2616, section 14.30. 
     11        # This is only possible if the host name can be gleaned from request. 
     12        if 'Location' in response.headers and http.get_host(request): 
     13            response['Location'] = request.build_absolute_uri(response['Location']) 
     14        return response 
     15 
    616class BaseHandler(object): 
     17    compulsary_middleware = BaseCompulsaryMiddleware 
     18 
    719    def __init__(self): 
    820        self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None 
    921 
     
    1527        """ 
    1628        from django.conf import settings 
    1729        from django.core import exceptions 
    18         self._request_middleware = [] 
    19         self._view_middleware = [] 
    20         self._response_middleware = [] 
    21         self._exception_middleware = [] 
     30 
     31        middleware_classes = [self.compulsary_middleware] 
    2232        for middleware_path in settings.MIDDLEWARE_CLASSES: 
    2333            try: 
    2434                dot = middleware_path.rindex('.') 
     
    3040            except ImportError, e: 
    3141                raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) 
    3242            try: 
    33                 mw_class = getattr(mod, mw_classname) 
     43                middleware_classes.append(getattr(mod, mw_classname)) 
    3444            except AttributeError: 
    3545                raise exceptions.ImproperlyConfigured, 'Middleware module "%s" does not define a "%s" class' % (mw_module, mw_classname) 
    3646 
     47        self._request_middleware = [] 
     48        self._view_middleware = [] 
     49        self._response_middleware = [] 
     50        self._exception_middleware = [] 
     51        for mw_class in middleware_classes: 
    3752            try: 
    3853                mw_instance = mw_class() 
    3954            except exceptions.MiddlewareNotUsed: 
    4055                continue 
    41  
    4256            if hasattr(mw_instance, 'process_request'): 
    4357                self._request_middleware.append(mw_instance.process_request) 
    4458            if hasattr(mw_instance, 'process_view'): 
  • django/http/__init__.py

     
    22from Cookie import SimpleCookie 
    33from pprint import pformat 
    44from urllib import urlencode, quote 
     5from urlparse import urljoin 
    56from django.utils.datastructures import MultiValueDict 
    67 
    78RESERVED_CHARS="!*'();:@&=+$,/?%#[]" 
     
    3940    def get_full_path(self): 
    4041        return '' 
    4142 
     43    def build_absolute_uri(self, location=None): 
     44        """ 
     45        Builds an absolute URI from the location and the variables available in 
     46        this request. If no location is specified, the absolute URI is built on 
     47        ``request.get_full_path()``. 
     48        """ 
     49        if not location: 
     50            location = request.get_full_path() 
     51        if not ':' in location: 
     52            current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http', 
     53                                         get_host(self), self.path) 
     54            location = urljoin(current_uri, location) 
     55        return location 
     56 
    4257    def is_secure(self): 
    4358        return os.environ.get("HTTPS") == "on" 
    4459 
  • django/test/testcases.py

     
    5757        self._pre_setup() 
    5858        super(TestCase, self).__call__(result) 
    5959 
    60     def assertRedirects(self, response, expected_path, status_code=302, target_status_code=200): 
     60    def assertRedirects(self, response, expected_url, status_code=302, target_status_code=200): 
    6161        """Assert that a response redirected to a specific URL, and that the 
    6262        redirect URL can be loaded. 
    6363         
     
    6565        self.assertEqual(response.status_code, status_code,  
    6666            "Response didn't redirect as expected: Reponse code was %d (expected %d)" %  
    6767                (response.status_code, status_code)) 
    68         scheme, netloc, path, params, query, fragment = urlparse(response['Location']) 
    69         self.assertEqual(path, expected_path,  
    70             "Response redirected to '%s', expected '%s'" % (path, expected_path)) 
     68        url = response['Location'] 
     69        scheme, netloc, path, params, query, fragment = urlparse(url) 
     70        self.assertEqual(url, expected_url,  
     71            "Response redirected to '%s', expected '%s'" % (url, expected_url)) 
    7172        redirect_response = self.client.get(path) 
    7273        self.assertEqual(redirect_response.status_code, target_status_code,  
    7374            "Couldn't retrieve redirection page '%s': response code was %d (expected %d)" %  
  • docs/request_response.txt

     
    151151 
    152152   Example: ``"/music/bands/the_beatles/?print=true"`` 
    153153 
     154``build_absolute_uri(location)`` 
     155   Returns an absolute URI from the location. If no location is provided, the 
     156   location will be set to ``request.get_full_path()``. 
     157 
     158   If the location is already an absolute URI, it will not be altered, 
     159   otherwise the absolute URI is built using the server variables available in 
     160   this request. 
     161 
     162   Example: ``"http://example.com/music/bands/the_beatles/?print=true"`` 
     163 
    154164``is_secure()`` 
    155165   Returns ``True`` if the request is secure; that is, if it was made with 
    156166   HTTPS. 
  • tests/modeltests/test_client/models.py

     
    7878 
    7979    def test_redirect(self): 
    8080        "GET a URL that redirects elsewhere" 
    81         response = self.client.get('/test_client/redirect_view/') 
    82          
     81        response = self.client.get('/test_client/redirect_view/')         
    8382        # Check that the response was a 302 (redirect) 
    8483        self.assertRedirects(response, '/test_client/get_view/') 
     84         
     85        client_providing_host = Client(HTTP_HOST='django.testserver') 
     86        response = client_providing_host.get('/test_client/redirect_view/') 
     87        # Check that the response was a 302 (redirect) with absolute URI 
     88        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/') 
    8589 
    8690    def test_permanent_redirect(self): 
    8791        "GET a URL that redirects permanently elsewhere" 
    8892        response = self.client.get('/test_client/permanent_redirect_view/') 
    89          
    9093        # Check that the response was a 301 (permanent redirect) 
    9194        self.assertRedirects(response, '/test_client/get_view/', status_code=301) 
    9295 
     96        client_providing_host = Client(HTTP_HOST='django.testserver') 
     97        response = client_providing_host.get('/test_client/permanent_redirect_view/') 
     98        # Check that the response was a 301 (permanent redirect) with absolute URI 
     99        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) 
     100 
    93101    def test_redirect_to_strange_location(self): 
    94102        "GET a URL that redirects to a non-200 page" 
    95103        response = self.client.get('/test_client/double_redirect_view/') 
     
    208216         
    209217        # Get the page without logging in. Should result in 302. 
    210218        response = self.client.get('/test_client/login_protected_view/') 
    211         self.assertRedirects(response, '/accounts/login/') 
     219        self.assertRedirects(response, '/accounts/login/?next=/test_client/login_protected_view/') 
    212220         
    213221        # Log in 
    214222        self.client.login(username='testclient', password='password')