Ticket #18314: 18314.diff

File 18314.diff, 5.5 KB (added by Chris Beaven, 12 years ago)
  • django/http/__init__.py

    diff --git a/django/http/__init__.py b/django/http/__init__.py
    index 2bad146..0c752e6 100644
    a b import warnings  
    1010from io import BytesIO
    1111from pprint import pformat
    1212from urllib import urlencode, quote
    13 from urlparse import urljoin, parse_qsl
     13from urlparse import urljoin, urlsplit, parse_qsl
    1414
    1515import Cookie
    1616# Some versions of Python 2.7 and later won't need this encoding bug fix:
    from django.utils import timezone  
    8686
    8787RESERVED_CHARS="!*'();:@&=+$,/?%#[]"
    8888
    89 absolute_http_url_re = re.compile(r"^https?://", re.I)
    90 
    9189class Http404(Exception):
    9290    pass
    9391
    class HttpRequest(object):  
    205203
    206204    def build_absolute_uri(self, location=None):
    207205        """
    208         Builds an absolute URI from the location and the variables available in
    209         this request. If no location is specified, the absolute URI is built on
    210         ``request.get_full_path()``.
     206        Builds an absolute URI, using location and/or variables available in
     207        the request, and returns it.
     208
     209        If ``location`` is provided and is absolute, it is simply converted to
     210        an RFC 3987 compliant URI and returned.
     211
     212        If ``location`` is provided but is does not provide both a scheme and
     213        domain, it is urljoined to a base URL constructed from the request
     214        variables.
    211215        """
    212216        if not location:
    213             location = self.get_full_path()
    214         if not absolute_http_url_re.match(location):
    215             current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
    216                                          self.get_host(), self.path)
     217            # Make it an absolute url (but schemeless and domainless) for the
     218            # edge case that the path starts with '//'.
     219            location = '//%s' % self.get_full_path()
     220        bits = urlsplit(location)
     221        if not bits.scheme or not bits.netloc:
     222            current_uri = '%(scheme)s://%(host)s%(path)s' % {
     223                'scheme': 'https' if self.is_secure() else 'http',
     224                'host': self.get_host(),
     225                'path': self.path
     226            }
     227            # Join the constructed URL with the provided location, which will
     228            # allow the provided ``location`` to apply query strings to the
     229            # base path as well as override the host, if it begins with //
    217230            location = urljoin(current_uri, location)
    218231        return iri_to_uri(location)
    219232
    def str_to_unicode(s, encoding):  
    750763        return unicode(s, encoding, 'replace')
    751764    else:
    752765        return s
    753 
  • new file tests/regressiontests/http/tests.py

    diff --git a/tests/regressiontests/http/__init__.py b/tests/regressiontests/http/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/http/models.py b/tests/regressiontests/http/models.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/http/tests.py b/tests/regressiontests/http/tests.py
    new file mode 100644
    index 0000000..8da954a
    - +  
     1from django.utils import unittest
     2from django.test.client import RequestFactory
     3
     4
     5class HttpRequestTestCase(unittest.TestCase):
     6    """
     7    Regression tests for ticket #18314.
     8    """
     9    def setUp(self):
     10        """
     11        Attaches a request factory.
     12        """
     13        self.factory = RequestFactory()
     14
     15    def test_build_absolute_uri_no_location(self):
     16        """
     17        Ensures that ``request.build_absolute_uri()`` returns the proper value
     18        when the ``location`` argument is not provided, and ``request.path``
     19        begins with //.
     20        """
     21        # //// is needed to create a request with a path beginning with //
     22        request = self.factory.get('////django-ate-my-baby')
     23        self.assertEqual(
     24            request.build_absolute_uri(),
     25            'http://testserver//django-ate-my-baby'
     26        )
     27
     28    def test_build_absolute_uri_absolute_location(self):
     29        """
     30        Ensures that ``request.build_absolute_uri()`` returns the proper value
     31        when an absolute URL ``location`` argument is provided, and
     32        ``request.path`` begins with //.
     33        """
     34        # //// is needed to create a request with a path beginning with //
     35        request = self.factory.get('////django-ate-my-baby')
     36        self.assertEqual(
     37            request.build_absolute_uri(location='http://example.com/?foo=bar'),
     38            'http://example.com/?foo=bar'
     39        )
     40
     41    def test_build_absolute_uri_schema_relative_location(self):
     42        """
     43        Ensures that ``request.build_absolute_uri()`` returns the proper value
     44        when a schema-relative URL ``location`` argument is provided, and
     45        ``request.path`` begins with //.
     46        """
     47        # //// is needed to create a request with a path beginning with //
     48        request = self.factory.get('////django-ate-my-baby')
     49        self.assertEqual(
     50            request.build_absolute_uri(location='//example.com/?foo=bar'),
     51            'http://example.com/?foo=bar'
     52        )
     53
     54    def test_build_absolute_uri_relative_location(self):
     55        """
     56        Ensures that ``request.build_absolute_uri()`` returns the proper value
     57        when a relative URL ``location`` argument is provided, and
     58        ``request.path`` begins with //.
     59        """
     60        # //// is needed to create a request with a path beginning with //
     61        request = self.factory.get('////django-ate-my-baby')
     62        self.assertEqual(
     63            request.build_absolute_uri(location='/foo/bar/'),
     64            'http://testserver/foo/bar/'
     65        )
Back to Top