Fixed #25211 -- Added HttpRequest.get_port() and USE_X_FORWARDED_PORT setting.
This commit is contained in:
parent
f6259ce776
commit
4dcfbd7923
|
@ -428,6 +428,7 @@ DEFAULT_INDEX_TABLESPACE = ''
|
||||||
X_FRAME_OPTIONS = 'SAMEORIGIN'
|
X_FRAME_OPTIONS = 'SAMEORIGIN'
|
||||||
|
|
||||||
USE_X_FORWARDED_HOST = False
|
USE_X_FORWARDED_HOST = False
|
||||||
|
USE_X_FORWARDED_PORT = False
|
||||||
|
|
||||||
# The Python dotted path to the WSGI application that Django's internal server
|
# The Python dotted path to the WSGI application that Django's internal server
|
||||||
# (runserver) will use. If `None`, the return value of
|
# (runserver) will use. If `None`, the return value of
|
||||||
|
|
|
@ -79,7 +79,7 @@ class HttpRequest(object):
|
||||||
else:
|
else:
|
||||||
# Reconstruct the host using the algorithm from PEP 333.
|
# Reconstruct the host using the algorithm from PEP 333.
|
||||||
host = self.META['SERVER_NAME']
|
host = self.META['SERVER_NAME']
|
||||||
server_port = str(self.META['SERVER_PORT'])
|
server_port = self.get_port()
|
||||||
if server_port != ('443' if self.is_secure() else '80'):
|
if server_port != ('443' if self.is_secure() else '80'):
|
||||||
host = '%s:%s' % (host, server_port)
|
host = '%s:%s' % (host, server_port)
|
||||||
|
|
||||||
|
@ -98,6 +98,14 @@ class HttpRequest(object):
|
||||||
msg += " The domain name provided is not valid according to RFC 1034/1035."
|
msg += " The domain name provided is not valid according to RFC 1034/1035."
|
||||||
raise DisallowedHost(msg)
|
raise DisallowedHost(msg)
|
||||||
|
|
||||||
|
def get_port(self):
|
||||||
|
"""Return the port number for the request as a string."""
|
||||||
|
if settings.USE_X_FORWARDED_PORT and 'HTTP_X_FORWARDED_PORT' in self.META:
|
||||||
|
port = self.META['HTTP_X_FORWARDED_PORT']
|
||||||
|
else:
|
||||||
|
port = self.META['SERVER_PORT']
|
||||||
|
return str(port)
|
||||||
|
|
||||||
def get_full_path(self, force_append_slash=False):
|
def get_full_path(self, force_append_slash=False):
|
||||||
# RFC 3986 requires query string arguments to be in the ASCII range.
|
# RFC 3986 requires query string arguments to be in the ASCII range.
|
||||||
# Rather than crash if this doesn't happen, we encode defensively.
|
# Rather than crash if this doesn't happen, we encode defensively.
|
||||||
|
|
|
@ -254,6 +254,14 @@ Methods
|
||||||
:class:`~django.middleware.common.CommonMiddleware` or
|
:class:`~django.middleware.common.CommonMiddleware` or
|
||||||
:class:`~django.middleware.csrf.CsrfViewMiddleware`.
|
:class:`~django.middleware.csrf.CsrfViewMiddleware`.
|
||||||
|
|
||||||
|
.. method:: HttpRequest.get_port()
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Returns the originating port of the request using information from the
|
||||||
|
``HTTP_X_FORWARDED_PORT`` (if :setting:`USE_X_FORWARDED_PORT` is enabled)
|
||||||
|
and ``SERVER_PORT`` ``META`` variables, in that order.
|
||||||
|
|
||||||
.. method:: HttpRequest.get_full_path()
|
.. method:: HttpRequest.get_full_path()
|
||||||
|
|
||||||
Returns the ``path``, plus an appended query string, if applicable.
|
Returns the ``path``, plus an appended query string, if applicable.
|
||||||
|
|
|
@ -2621,6 +2621,19 @@ A boolean that specifies whether to use the X-Forwarded-Host header in
|
||||||
preference to the Host header. This should only be enabled if a proxy
|
preference to the Host header. This should only be enabled if a proxy
|
||||||
which sets this header is in use.
|
which sets this header is in use.
|
||||||
|
|
||||||
|
.. setting:: USE_X_FORWARDED_PORT
|
||||||
|
|
||||||
|
USE_X_FORWARDED_PORT
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
A boolean that specifies whether to use the X-Forwarded-Port header in
|
||||||
|
preference to the ``SERVER_PORT`` ``META`` variable. This should only be
|
||||||
|
enabled if a proxy which sets this header is in use.
|
||||||
|
|
||||||
.. setting:: WSGI_APPLICATION
|
.. setting:: WSGI_APPLICATION
|
||||||
|
|
||||||
WSGI_APPLICATION
|
WSGI_APPLICATION
|
||||||
|
@ -3329,6 +3342,7 @@ HTTP
|
||||||
* :setting:`SIGNING_BACKEND`
|
* :setting:`SIGNING_BACKEND`
|
||||||
* :setting:`USE_ETAGS`
|
* :setting:`USE_ETAGS`
|
||||||
* :setting:`USE_X_FORWARDED_HOST`
|
* :setting:`USE_X_FORWARDED_HOST`
|
||||||
|
* :setting:`USE_X_FORWARDED_PORT`
|
||||||
* :setting:`WSGI_APPLICATION`
|
* :setting:`WSGI_APPLICATION`
|
||||||
|
|
||||||
Logging
|
Logging
|
||||||
|
|
|
@ -538,6 +538,9 @@ Requests and Responses
|
||||||
returning an :class:`~django.http.HttpResponseForbidden` so that
|
returning an :class:`~django.http.HttpResponseForbidden` so that
|
||||||
:data:`~django.conf.urls.handler403` is invoked.
|
:data:`~django.conf.urls.handler403` is invoked.
|
||||||
|
|
||||||
|
* Added :meth:`HttpRequest.get_port() <django.http.HttpRequest.get_port>` to
|
||||||
|
fetch the originating port of the request.
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
||||||
|
|
|
@ -651,6 +651,38 @@ class HostValidationTests(SimpleTestCase):
|
||||||
}
|
}
|
||||||
request.get_host()
|
request.get_host()
|
||||||
|
|
||||||
|
@override_settings(USE_X_FORWARDED_PORT=False)
|
||||||
|
def test_get_port(self):
|
||||||
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
|
'SERVER_PORT': '8080',
|
||||||
|
'HTTP_X_FORWARDED_PORT': '80',
|
||||||
|
}
|
||||||
|
# Shouldn't use the X-Forwarded-Port header
|
||||||
|
self.assertEqual(request.get_port(), '8080')
|
||||||
|
|
||||||
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
|
'SERVER_PORT': '8080',
|
||||||
|
}
|
||||||
|
self.assertEqual(request.get_port(), '8080')
|
||||||
|
|
||||||
|
@override_settings(USE_X_FORWARDED_PORT=True)
|
||||||
|
def test_get_port_with_x_forwarded_port(self):
|
||||||
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
|
'SERVER_PORT': '8080',
|
||||||
|
'HTTP_X_FORWARDED_PORT': '80',
|
||||||
|
}
|
||||||
|
# Should use the X-Forwarded-Port header
|
||||||
|
self.assertEqual(request.get_port(), '80')
|
||||||
|
|
||||||
|
request = HttpRequest()
|
||||||
|
request.META = {
|
||||||
|
'SERVER_PORT': '8080',
|
||||||
|
}
|
||||||
|
self.assertEqual(request.get_port(), '8080')
|
||||||
|
|
||||||
@override_settings(DEBUG=True, ALLOWED_HOSTS=[])
|
@override_settings(DEBUG=True, ALLOWED_HOSTS=[])
|
||||||
def test_host_validation_disabled_in_debug_mode(self):
|
def test_host_validation_disabled_in_debug_mode(self):
|
||||||
"""If ALLOWED_HOSTS is empty and DEBUG is True, all hosts pass."""
|
"""If ALLOWED_HOSTS is empty and DEBUG is True, all hosts pass."""
|
||||||
|
|
Loading…
Reference in New Issue