summaryrefslogtreecommitdiff
path: root/django/http/request.py
diff options
context:
space:
mode:
authorUnai Zalakain <unai@gisa-elkartea.org>2013-11-04 00:34:11 +0100
committerTim Graham <timograham@gmail.com>2014-06-07 08:59:02 -0400
commit11284a63d48c84f1d60b5686d55cf8a9f8d64422 (patch)
tree6c16ab34fae64bbdc37ac7d5f990b979598b7a17 /django/http/request.py
parent9ed4a8c6b1a552a03fd27b77f1b742e3f9c66bde (diff)
Fixed #18314 -- Corrected request.build_absolute_uri() handling of paths starting with //
``HttpRequest.build_absolute_uri()`` now correctly handles paths starting with ``//``. ``WSGIRequest`` now doesn't remove all the leading slashes either, because ``http://test/server`` and http://test//server`` aren't the same thing (RFC2396). Thanks to SmileyChris for the initial patch.
Diffstat (limited to 'django/http/request.py')
-rw-r--r--django/http/request.py27
1 files changed, 19 insertions, 8 deletions
diff --git a/django/http/request.py b/django/http/request.py
index ded4744a87..84457c5300 100644
--- a/django/http/request.py
+++ b/django/http/request.py
@@ -15,7 +15,7 @@ from django.http.multipartparser import MultiPartParser, MultiPartParserError
from django.utils import six
from django.utils.datastructures import MultiValueDict, ImmutableList
from django.utils.encoding import force_bytes, force_text, force_str, iri_to_uri
-from django.utils.six.moves.urllib.parse import parse_qsl, urlencode, quote, urljoin
+from django.utils.six.moves.urllib.parse import parse_qsl, urlencode, quote, urljoin, urlsplit
RAISE_ERROR = object()
@@ -119,14 +119,25 @@ class HttpRequest(object):
def build_absolute_uri(self, location=None):
"""
Builds an absolute URI from the location and the variables available in
- this request. If no location is specified, the absolute URI is built on
- ``request.get_full_path()``.
+ this request. If no ``location`` is specified, the absolute URI is
+ built on ``request.get_full_path()``. Anyway, if the location is
+ absolute, it is simply converted to an RFC 3987 compliant URI and
+ returned and if location is relative or is scheme-relative (i.e.,
+ ``//example.com/``), it is urljoined to a base URL constructed from the
+ request variables.
"""
- if not location:
- location = self.get_full_path()
- if not absolute_http_url_re.match(location):
- current_uri = '%s://%s%s' % (self.scheme,
- self.get_host(), self.path)
+ if location is None:
+ # Make it an absolute url (but schemeless and domainless) for the
+ # edge case that the path starts with '//'.
+ location = '//%s' % self.get_full_path()
+ bits = urlsplit(location)
+ if not (bits.scheme and bits.netloc):
+ current_uri = '{scheme}://{host}{path}'.format(scheme=self.scheme,
+ host=self.get_host(),
+ path=self.path)
+ # Join the constructed URL with the provided location, which will
+ # allow the provided ``location`` to apply query strings to the
+ # base path as well as override the host, if it begins with //
location = urljoin(current_uri, location)
return iri_to_uri(location)