Ticket #987: redirect_absoluteuri.2.patch

File redirect_absoluteuri.2.patch, 8.1 KB (added by Chris Beaven, 17 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')
Back to Top