Django

Code

Changeset 6164

Show
Ignore:
Timestamp:
09/14/07 00:28:00 (10 months ago)
Author:
mtredinnick
Message:

Fixed #987 -- Convert relative URI portions into absolute URIs in HTTP Location headers. Based on a patch from SmileyChris?.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/core/handlers/base.py

    r4265 r6164  
    5151    def get_response(self, request): 
    5252        "Returns an HttpResponse object for the given HttpRequest" 
     53        response = self._real_get_response(request) 
     54        return fix_location_header(request, response) 
     55 
     56    def _real_get_response(self, request): 
    5357        from django.core import exceptions, urlresolvers 
    5458        from django.core.mail import mail_admins 
     
    130134        import traceback 
    131135        return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info()))) 
     136 
     137def fix_location_header(request, response): 
     138    """ 
     139    Ensure that we always use an absolute URI in any location header in the 
     140    response. This is required by RFC 2616, section 14.30. 
     141 
     142    Code constructing response objects is free to insert relative paths and 
     143    this function converts them to absolute paths. 
     144    """ 
     145    if 'Location' in response.headers and http.get_host(request): 
     146        response['Location'] = request.build_absolute_uri(response['Location']) 
     147    return response 
     148 
  • django/trunk/django/http/__init__.py

    r6098 r6164  
    33from pprint import pformat 
    44from urllib import urlencode 
     5from urlparse import urljoin 
    56from django.utils.datastructures import MultiValueDict, FileDict 
    67from django.utils.encoding import smart_str, iri_to_uri, force_unicode 
     
    4344 
    4445    __contains__ = has_key 
    45          
     46 
    4647    def get_full_path(self): 
    4748        return '' 
     49 
     50    def build_absolute_uri(self, location=None): 
     51        """ 
     52        Builds an absolute URI from the location and the variables available in 
     53        this request. If no location is specified, the absolute URI is built on 
     54        ``request.get_full_path()``. 
     55        """ 
     56        if not location: 
     57            location = request.get_full_path() 
     58        if not ':' in location: 
     59            current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http', 
     60                                         get_host(self), self.path) 
     61            location = urljoin(current_uri, location) 
     62        return location 
    4863 
    4964    def is_secure(self): 
  • django/trunk/django/test/testcases.py

    r6044 r6164  
    8585            ("Response didn't redirect as expected: Response code was %d" 
    8686             " (expected %d)" % (response.status_code, status_code))) 
    87         scheme, netloc, path, query, fragment = urlsplit(response['Location']) 
    88         url = path 
    89         if query: 
    90             url += '?' + query 
    91         if fragment: 
    92             url += '#' + fragment 
     87        url = response['Location'] 
     88        scheme, netloc, path, query, fragment = urlsplit(url) 
    9389        self.assertEqual(url, expected_url, 
    9490            "Response redirected to '%s', expected '%s'" % (url, expected_url)) 
  • django/trunk/docs/request_response.txt

    r6160 r6164  
    161161 
    162162   Example: ``"/music/bands/the_beatles/?print=true"`` 
     163 
     164``build_absolute_uri(location)`` 
     165   Returns the absolute URI form of ``location``. If no location is provided, 
     166   the location will be set to ``request.get_full_path()``. 
     167 
     168   If the location is already an absolute URI, it will not be altered. 
     169   Otherwise the absolute URI is built using the server variables available in 
     170   this request. 
     171 
     172   Example: ``"http://example.com/music/bands/the_beatles/?print=true"`` 
    163173 
    164174``is_secure()`` 
  • django/trunk/tests/modeltests/test_client/models.py

    r6039 r6164  
    8484        "GET a URL that redirects elsewhere" 
    8585        response = self.client.get('/test_client/redirect_view/') 
    86          
    8786        # Check that the response was a 302 (redirect) 
    8887        self.assertRedirects(response, '/test_client/get_view/') 
     88         
     89        client_providing_host = Client(HTTP_HOST='django.testserver') 
     90        response = client_providing_host.get('/test_client/redirect_view/') 
     91        # Check that the response was a 302 (redirect) with absolute URI 
     92        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/') 
    8993     
    9094    def test_redirect_with_query(self): 
     
    98102        "GET a URL that redirects permanently elsewhere" 
    99103        response = self.client.get('/test_client/permanent_redirect_view/') 
    100          
    101104        # Check that the response was a 301 (permanent redirect) 
    102105        self.assertRedirects(response, '/test_client/get_view/', status_code=301) 
     106 
     107        client_providing_host = Client(HTTP_HOST='django.testserver') 
     108        response = client_providing_host.get('/test_client/permanent_redirect_view/') 
     109        # Check that the response was a 301 (permanent redirect) with absolute URI 
     110        self.assertRedirects(response, 'http://django.testserver/test_client/get_view/', status_code=301) 
    103111 
    104112    def test_redirect_to_strange_location(self):