diff options
Diffstat (limited to 'django/http')
| -rw-r--r-- | django/http/request.py | 27 |
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) |
