Fixed #23960 -- Removed http.fix_location_header
Thanks Carl Meyer for the report and Tim Graham for the review.
This commit is contained in:
parent
0339844b70
commit
a0c2eb46dd
|
@ -23,7 +23,6 @@ logger = logging.getLogger('django.request')
|
|||
class BaseHandler(object):
|
||||
# Changes that are always applied to a response (in this order).
|
||||
response_fixes = [
|
||||
http.fix_location_header,
|
||||
http.conditional_content_removal,
|
||||
]
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.http.response import (
|
|||
HttpResponseNotFound, HttpResponseNotAllowed, HttpResponseGone,
|
||||
HttpResponseServerError, Http404, BadHeaderError, JsonResponse,
|
||||
)
|
||||
from django.http.utils import fix_location_header, conditional_content_removal
|
||||
from django.http.utils import conditional_content_removal
|
||||
|
||||
__all__ = [
|
||||
'SimpleCookie', 'parse_cookie', 'HttpRequest', 'QueryDict',
|
||||
|
@ -17,6 +17,6 @@ __all__ = [
|
|||
'HttpResponsePermanentRedirect', 'HttpResponseNotModified',
|
||||
'HttpResponseBadRequest', 'HttpResponseForbidden', 'HttpResponseNotFound',
|
||||
'HttpResponseNotAllowed', 'HttpResponseGone', 'HttpResponseServerError',
|
||||
'Http404', 'BadHeaderError', 'fix_location_header', 'JsonResponse',
|
||||
'FileResponse', 'conditional_content_removal',
|
||||
'Http404', 'BadHeaderError', 'JsonResponse', 'FileResponse',
|
||||
'conditional_content_removal',
|
||||
]
|
||||
|
|
|
@ -9,19 +9,6 @@ Functions that modify an HTTP request or response in some way.
|
|||
# universally applicable.
|
||||
|
||||
|
||||
def fix_location_header(request, response):
|
||||
"""
|
||||
Ensures that we always use an absolute URI in any location header in the
|
||||
response. This is required by RFC 2616, section 14.30.
|
||||
|
||||
Code constructing response objects is free to insert relative paths, as
|
||||
this function converts them to absolute paths.
|
||||
"""
|
||||
if 'Location' in response:
|
||||
response['Location'] = request.build_absolute_uri(response['Location'])
|
||||
return response
|
||||
|
||||
|
||||
def conditional_content_removal(request, response):
|
||||
"""
|
||||
Removes the content of responses for HEAD requests, 1xx, 204 and 304
|
||||
|
|
|
@ -86,7 +86,7 @@ class CommonMiddleware(object):
|
|||
if new_url == old_url:
|
||||
# No redirects required.
|
||||
return
|
||||
if new_url[0]:
|
||||
if new_url[0] != old_url[0]:
|
||||
newurl = "%s://%s%s" % (
|
||||
request.scheme,
|
||||
new_url[0], urlquote(new_url[1]))
|
||||
|
|
|
@ -40,16 +40,12 @@ class LocaleMiddleware(object):
|
|||
|
||||
if path_valid:
|
||||
script_prefix = get_script_prefix()
|
||||
language_url = "%s://%s%s" % (
|
||||
request.scheme,
|
||||
request.get_host(),
|
||||
# insert language after the script prefix and before the
|
||||
# rest of the URL
|
||||
request.get_full_path().replace(
|
||||
script_prefix,
|
||||
'%s%s/' % (script_prefix, language),
|
||||
1
|
||||
)
|
||||
# Insert language after the script prefix and before the
|
||||
# rest of the URL
|
||||
language_url = request.get_full_path().replace(
|
||||
script_prefix,
|
||||
'%s%s/' % (script_prefix, language),
|
||||
1
|
||||
)
|
||||
return self.response_redirect_class(language_url)
|
||||
|
||||
|
|
|
@ -37,7 +37,9 @@ from django.test.utils import (
|
|||
override_settings,
|
||||
)
|
||||
from django.utils import six
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.deprecation import (
|
||||
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||
)
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.six.moves.urllib.parse import (
|
||||
unquote, urlparse, urlsplit, urlunsplit,
|
||||
|
@ -249,11 +251,15 @@ class SimpleTestCase(unittest.TestCase):
|
|||
TestClient to do a request (use fetch_redirect_response=False to check
|
||||
such links without fetching them).
|
||||
"""
|
||||
if host is not None:
|
||||
warnings.warn(
|
||||
"The host argument is deprecated and no longer used by assertRedirects",
|
||||
RemovedInDjango21Warning, stacklevel=2
|
||||
)
|
||||
|
||||
if msg_prefix:
|
||||
msg_prefix += ": "
|
||||
|
||||
e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
|
||||
|
||||
if hasattr(response, 'redirect_chain'):
|
||||
# The request was a followed redirect
|
||||
self.assertTrue(len(response.redirect_chain) > 0,
|
||||
|
@ -295,10 +301,18 @@ class SimpleTestCase(unittest.TestCase):
|
|||
" response code was %d (expected %d)" %
|
||||
(path, redirect_response.status_code, target_status_code))
|
||||
|
||||
e_scheme = e_scheme if e_scheme else scheme or 'http'
|
||||
e_netloc = e_netloc if e_netloc else host or 'testserver'
|
||||
expected_url = urlunsplit((e_scheme, e_netloc, e_path, e_query,
|
||||
e_fragment))
|
||||
if url != expected_url:
|
||||
# For temporary backwards compatibility, try to compare with a relative url
|
||||
e_scheme, e_netloc, e_path, e_query, e_fragment = urlsplit(expected_url)
|
||||
relative_url = urlunsplit(('', '', e_path, e_query, e_fragment))
|
||||
if url == relative_url:
|
||||
warnings.warn(
|
||||
"assertRedirects had to strip the scheme and domain from the "
|
||||
"expected URL, as it was always added automatically to URLs "
|
||||
"before Django 1.9. Please update your expected URLs by "
|
||||
"removing the scheme and domain.",
|
||||
RemovedInDjango21Warning, stacklevel=2)
|
||||
expected_url = relative_url
|
||||
|
||||
self.assertEqual(url, expected_url,
|
||||
msg_prefix + "Response redirected to '%s', expected '%s'" %
|
||||
|
|
|
@ -22,6 +22,10 @@ details on these changes.
|
|||
|
||||
* The ``assignment_tag`` helper will be removed.
|
||||
|
||||
* The ``host`` argument to ``assertsRedirects`` will be removed. The
|
||||
compatibility layer which allows absolute URLs to be considered equal to
|
||||
relative ones when the path is identical will also be removed.
|
||||
|
||||
.. _deprecation-removed-in-2.0:
|
||||
|
||||
2.0
|
||||
|
|
|
@ -824,8 +824,10 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
|
|||
|
||||
The first argument to the constructor is required -- the path to redirect
|
||||
to. This can be a fully qualified URL
|
||||
(e.g. ``'http://www.yahoo.com/search/'``) or an absolute path with no
|
||||
domain (e.g. ``'/search/'``). See :class:`HttpResponse` for other optional
|
||||
(e.g. ``'http://www.yahoo.com/search/'``), an absolute path with no domain
|
||||
(e.g. ``'/search/'``), or even a relative path (e.g. ``'search/'``). In that
|
||||
last case, the client browser will reconstruct the full URL itself
|
||||
according to the current path. See :class:`HttpResponse` for other optional
|
||||
constructor arguments. Note that this returns an HTTP status code 302.
|
||||
|
||||
.. attribute:: HttpResponseRedirect.url
|
||||
|
|
|
@ -266,6 +266,21 @@ a directory. Now, Django only silences the exception if the template source
|
|||
does not exist. All other situations result in the original ``IOError`` being
|
||||
raised.
|
||||
|
||||
HTTP redirects no longer forced to absolute URIs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Relative redirects are no longer converted to absolute URIs. :rfc:`2616`
|
||||
required the ``Location`` header in redirect responses to be an absolute URI,
|
||||
but it has been superseded by :rfc:`7231` which allows relative URIs in
|
||||
``Location``, recognizing the actual practice of user agents, almost all of
|
||||
which support them.
|
||||
|
||||
Consequently, the expected URLs passed to ``assertRedirects`` should generally
|
||||
no longer include the scheme and domain part of the URLs. For example,
|
||||
``self.assertRedirects(response, 'http://testserver/some-url/')`` should be
|
||||
replaced by ``self.assertRedirects(response, '/some-url/')`` (unless the
|
||||
redirection specifically contained an absolute URL, of course).
|
||||
|
||||
Miscellaneous
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -1398,7 +1398,7 @@ your test suite.
|
|||
You can use this as a context manager in the same way as
|
||||
:meth:`~SimpleTestCase.assertTemplateUsed`.
|
||||
|
||||
.. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, host=None, msg_prefix='', fetch_redirect_response=True)
|
||||
.. method:: SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)
|
||||
|
||||
Asserts that the response returned a ``status_code`` redirect status,
|
||||
redirected to ``expected_url`` (including any ``GET`` data), and that the
|
||||
|
@ -1408,14 +1408,6 @@ your test suite.
|
|||
``target_status_code`` will be the url and status code for the final
|
||||
point of the redirect chain.
|
||||
|
||||
The ``host`` argument sets a default host if ``expected_url`` doesn't
|
||||
include one (e.g. ``"/bar/"``). If ``expected_url`` is an absolute URL that
|
||||
includes a host (e.g. ``"http://testhost/bar/"``), the ``host`` parameter
|
||||
will be ignored. Note that the test client doesn't support fetching external
|
||||
URLs, but the parameter may be useful if you are testing with a custom HTTP
|
||||
host (for example, initializing the test client with
|
||||
``Client(HTTP_HOST="testhost")``.
|
||||
|
||||
If ``fetch_redirect_response`` is ``False``, the final page won't be
|
||||
loaded. Since the test client can't fetch externals URLs, this is
|
||||
particularly useful if ``expected_url`` isn't part of your Django app.
|
||||
|
@ -1425,6 +1417,11 @@ your test suite.
|
|||
the original request's scheme is used. If present, the scheme in
|
||||
``expected_url`` is the one used to make the comparisons to.
|
||||
|
||||
.. deprecated:: 1.9
|
||||
|
||||
The ``host`` argument is deprecated, as redirections are no longer
|
||||
forced to be absolute URLs.
|
||||
|
||||
.. method:: SimpleTestCase.assertHTMLEqual(html1, html2, msg=None)
|
||||
|
||||
Asserts that the strings ``html1`` and ``html2`` are equal. The comparison
|
||||
|
|
|
@ -87,7 +87,7 @@ class BasicFormTests(TestCase):
|
|||
|
||||
def test_post_data(self):
|
||||
res = self.client.post('/contact/', {'name': "Me", 'message': "Hello"})
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
|
||||
|
||||
class ModelFormMixinTests(TestCase):
|
||||
|
@ -117,7 +117,7 @@ class CreateViewTests(TestCase):
|
|||
res = self.client.post('/edit/authors/create/',
|
||||
{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
|
||||
|
||||
def test_create_invalid(self):
|
||||
|
@ -133,14 +133,14 @@ class CreateViewTests(TestCase):
|
|||
{'name': 'Rene Magritte'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
artist = Artist.objects.get(name='Rene Magritte')
|
||||
self.assertRedirects(res, 'http://testserver/detail/artist/%d/' % artist.pk)
|
||||
self.assertRedirects(res, '/detail/artist/%d/' % artist.pk)
|
||||
self.assertQuerysetEqual(Artist.objects.all(), ['<Artist: Rene Magritte>'])
|
||||
|
||||
def test_create_with_redirect(self):
|
||||
res = self.client.post('/edit/authors/create/redirect/',
|
||||
{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/edit/authors/create/')
|
||||
self.assertRedirects(res, '/edit/authors/create/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango20Warning)
|
||||
|
@ -152,7 +152,7 @@ class CreateViewTests(TestCase):
|
|||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe>'])
|
||||
self.assertEqual(res.status_code, 302)
|
||||
pk = Author.objects.first().pk
|
||||
self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk)
|
||||
self.assertRedirects(res, '/edit/author/%d/update/' % pk)
|
||||
# Also test with escaped chars in URL
|
||||
res = self.client.post(
|
||||
'/edit/authors/create/interpolate_redirect_nonascii/',
|
||||
|
@ -160,7 +160,7 @@ class CreateViewTests(TestCase):
|
|||
)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
pk = Author.objects.get(name='John Doe').pk
|
||||
self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk))
|
||||
self.assertRedirects(res, '/%C3%A9dit/author/{}/update/'.format(pk))
|
||||
|
||||
def test_create_with_special_properties(self):
|
||||
res = self.client.get('/edit/authors/create/special/')
|
||||
|
@ -189,7 +189,7 @@ class CreateViewTests(TestCase):
|
|||
res = self.client.post('/edit/authors/create/restricted/',
|
||||
{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/accounts/login/?next=/edit/authors/create/restricted/')
|
||||
self.assertRedirects(res, '/accounts/login/?next=/edit/authors/create/restricted/')
|
||||
|
||||
def test_create_view_with_restricted_fields(self):
|
||||
|
||||
|
@ -249,7 +249,7 @@ class UpdateViewTests(TestCase):
|
|||
res = self.client.post('/edit/author/%d/update/' % a.pk,
|
||||
{'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
|
||||
|
||||
def test_update_invalid(self):
|
||||
|
@ -269,7 +269,7 @@ class UpdateViewTests(TestCase):
|
|||
res = self.client.post('/edit/artists/%d/update/' % a.pk,
|
||||
{'name': 'Rene Magritte'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/detail/artist/%d/' % a.pk)
|
||||
self.assertRedirects(res, '/detail/artist/%d/' % a.pk)
|
||||
self.assertQuerysetEqual(Artist.objects.all(), ['<Artist: Rene Magritte>'])
|
||||
|
||||
def test_update_with_redirect(self):
|
||||
|
@ -280,7 +280,7 @@ class UpdateViewTests(TestCase):
|
|||
res = self.client.post('/edit/author/%d/update/redirect/' % a.pk,
|
||||
{'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/edit/authors/create/')
|
||||
self.assertRedirects(res, '/edit/authors/create/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango20Warning)
|
||||
|
@ -296,7 +296,7 @@ class UpdateViewTests(TestCase):
|
|||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
|
||||
self.assertEqual(res.status_code, 302)
|
||||
pk = Author.objects.first().pk
|
||||
self.assertRedirects(res, 'http://testserver/edit/author/%d/update/' % pk)
|
||||
self.assertRedirects(res, '/edit/author/%d/update/' % pk)
|
||||
# Also test with escaped chars in URL
|
||||
res = self.client.post(
|
||||
'/edit/author/%d/update/interpolate_redirect_nonascii/' % a.pk,
|
||||
|
@ -304,7 +304,7 @@ class UpdateViewTests(TestCase):
|
|||
)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
pk = Author.objects.get(name='John Doe').pk
|
||||
self.assertRedirects(res, 'http://testserver/%C3%A9dit/author/{}/update/'.format(pk))
|
||||
self.assertRedirects(res, '/%C3%A9dit/author/{}/update/'.format(pk))
|
||||
|
||||
def test_update_with_special_properties(self):
|
||||
a = Author.objects.create(
|
||||
|
@ -322,7 +322,7 @@ class UpdateViewTests(TestCase):
|
|||
res = self.client.post('/edit/author/%d/update/special/' % a.pk,
|
||||
{'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/detail/author/%d/' % a.pk)
|
||||
self.assertRedirects(res, '/detail/author/%d/' % a.pk)
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (author of xkcd)>'])
|
||||
|
||||
def test_update_without_redirect(self):
|
||||
|
@ -354,7 +354,7 @@ class UpdateViewTests(TestCase):
|
|||
res = self.client.post('/edit/author/update/',
|
||||
{'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'})
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Randall Munroe (xkcd)>'])
|
||||
|
||||
|
||||
|
@ -372,7 +372,7 @@ class DeleteViewTests(TestCase):
|
|||
# Deletion with POST
|
||||
res = self.client.post('/edit/author/%d/delete/' % a.pk)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), [])
|
||||
|
||||
def test_delete_by_delete(self):
|
||||
|
@ -380,14 +380,14 @@ class DeleteViewTests(TestCase):
|
|||
a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
res = self.client.delete('/edit/author/%d/delete/' % a.pk)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), [])
|
||||
|
||||
def test_delete_with_redirect(self):
|
||||
a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
res = self.client.post('/edit/author/%d/delete/redirect/' % a.pk)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/edit/authors/create/')
|
||||
self.assertRedirects(res, '/edit/authors/create/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), [])
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango20Warning)
|
||||
|
@ -395,13 +395,13 @@ class DeleteViewTests(TestCase):
|
|||
a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
res = self.client.post('/edit/author/%d/delete/interpolate_redirect/' % a.pk)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/edit/authors/create/?deleted=%d' % a.pk)
|
||||
self.assertRedirects(res, '/edit/authors/create/?deleted=%d' % a.pk)
|
||||
self.assertQuerysetEqual(Author.objects.all(), [])
|
||||
# Also test with escaped chars in URL
|
||||
a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
res = self.client.post('/edit/author/{}/delete/interpolate_redirect_nonascii/'.format(a.pk))
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/%C3%A9dit/authors/create/?deleted={}'.format(a.pk))
|
||||
self.assertRedirects(res, '/%C3%A9dit/authors/create/?deleted={}'.format(a.pk))
|
||||
|
||||
def test_delete_with_special_properties(self):
|
||||
a = Author.objects.create(**{'name': 'Randall Munroe', 'slug': 'randall-munroe'})
|
||||
|
@ -414,7 +414,7 @@ class DeleteViewTests(TestCase):
|
|||
|
||||
res = self.client.post('/edit/author/%d/delete/special/' % a.pk)
|
||||
self.assertEqual(res.status_code, 302)
|
||||
self.assertRedirects(res, 'http://testserver/list/authors/')
|
||||
self.assertRedirects(res, '/list/authors/')
|
||||
self.assertQuerysetEqual(Author.objects.all(), [])
|
||||
|
||||
def test_delete_without_redirect(self):
|
||||
|
|
|
@ -3,10 +3,8 @@ from __future__ import unicode_literals
|
|||
import gzip
|
||||
import io
|
||||
|
||||
from django.http import (
|
||||
HttpRequest, HttpResponse, HttpResponseRedirect, StreamingHttpResponse,
|
||||
)
|
||||
from django.http.utils import conditional_content_removal, fix_location_header
|
||||
from django.http import HttpRequest, HttpResponse, StreamingHttpResponse
|
||||
from django.http.utils import conditional_content_removal
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
|
@ -71,15 +69,3 @@ class HttpUtilTests(TestCase):
|
|||
res = StreamingHttpResponse(['abc'])
|
||||
conditional_content_removal(req, res)
|
||||
self.assertEqual(b''.join(res), b'')
|
||||
|
||||
def test_fix_location_without_get_host(self):
|
||||
"""
|
||||
Tests that you can return an absolute redirect when the request
|
||||
host is not in ALLOWED_HOSTS. Issue #20472
|
||||
"""
|
||||
request = HttpRequest()
|
||||
|
||||
def bomb():
|
||||
self.assertTrue(False)
|
||||
request.get_host = bomb
|
||||
fix_location_header(request, HttpResponseRedirect('http://example.com'))
|
||||
|
|
|
@ -248,7 +248,7 @@ class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase):
|
|||
def test_en_redirect(self):
|
||||
response = self.client.get('/account/register', HTTP_ACCEPT_LANGUAGE='en', follow=True)
|
||||
# target status code of 301 because of CommonMiddleware redirecting
|
||||
self.assertIn(('http://testserver/en/account/register/', 301), response.redirect_chain)
|
||||
self.assertIn(('/en/account/register/', 301), response.redirect_chain)
|
||||
self.assertRedirects(response, '/en/account/register/', 302)
|
||||
|
||||
response = self.client.get('/prefixed.xml', HTTP_ACCEPT_LANGUAGE='en', follow=True)
|
||||
|
|
|
@ -64,7 +64,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
request = self.rf.get('/slash')
|
||||
r = CommonMiddleware().process_request(request)
|
||||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(r.url, 'http://testserver/slash/')
|
||||
self.assertEqual(r.url, '/slash/')
|
||||
|
||||
@override_settings(APPEND_SLASH=True, DEBUG=True)
|
||||
def test_append_slash_no_redirect_on_POST_in_DEBUG(self):
|
||||
|
@ -106,7 +106,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(
|
||||
r.url,
|
||||
'http://testserver/needsquoting%23/')
|
||||
'/needsquoting%23/')
|
||||
|
||||
@override_settings(APPEND_SLASH=False, PREPEND_WWW=True)
|
||||
def test_prepend_www(self):
|
||||
|
@ -174,7 +174,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
self.assertIsNotNone(r,
|
||||
"CommonMiddlware failed to return APPEND_SLASH redirect using request.urlconf")
|
||||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(r.url, 'http://testserver/customurlconf/slash/')
|
||||
self.assertEqual(r.url, '/customurlconf/slash/')
|
||||
|
||||
@override_settings(APPEND_SLASH=True, DEBUG=True)
|
||||
def test_append_slash_no_redirect_on_POST_in_DEBUG_custom_urlconf(self):
|
||||
|
@ -212,7 +212,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(
|
||||
r.url,
|
||||
'http://testserver/customurlconf/needsquoting%23/')
|
||||
'/customurlconf/needsquoting%23/')
|
||||
|
||||
@override_settings(APPEND_SLASH=False, PREPEND_WWW=True)
|
||||
def test_prepend_www_custom_urlconf(self):
|
||||
|
@ -264,7 +264,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
request = self.rf.get('/slash')
|
||||
r = CommonMiddleware().process_request(request)
|
||||
self.assertEqual(r.status_code, 301)
|
||||
self.assertEqual(r.url, 'http://testserver/slash/')
|
||||
self.assertEqual(r.url, '/slash/')
|
||||
self.assertIsInstance(r, HttpResponsePermanentRedirect)
|
||||
|
||||
def test_response_redirect_class_subclass(self):
|
||||
|
@ -274,7 +274,7 @@ class CommonMiddlewareTest(TestCase):
|
|||
request = self.rf.get('/slash')
|
||||
r = MyCommonMiddleware().process_request(request)
|
||||
self.assertEqual(r.status_code, 302)
|
||||
self.assertEqual(r.url, 'http://testserver/slash/')
|
||||
self.assertEqual(r.url, '/slash/')
|
||||
self.assertIsInstance(r, HttpResponseRedirect)
|
||||
|
||||
|
||||
|
|
|
@ -176,40 +176,27 @@ class ClientTest(TestCase):
|
|||
def test_redirect(self):
|
||||
"GET a URL that redirects elsewhere"
|
||||
response = self.client.get('/redirect_view/')
|
||||
# Check that the response was a 302 (redirect) and that
|
||||
# assertRedirect() understands to put an implicit http://testserver/ in
|
||||
# front of non-absolute URLs.
|
||||
# Check that the response was a 302 (redirect)
|
||||
self.assertRedirects(response, '/get_view/')
|
||||
|
||||
host = 'django.testserver'
|
||||
client_providing_host = Client(HTTP_HOST=host)
|
||||
response = client_providing_host.get('/redirect_view/')
|
||||
# Check that the response was a 302 (redirect) with absolute URI
|
||||
self.assertRedirects(response, '/get_view/', host=host)
|
||||
|
||||
def test_redirect_with_query(self):
|
||||
"GET a URL that redirects with given GET parameters"
|
||||
response = self.client.get('/redirect_view/', {'var': 'value'})
|
||||
|
||||
# Check if parameters are intact
|
||||
self.assertRedirects(response, 'http://testserver/get_view/?var=value')
|
||||
self.assertRedirects(response, '/get_view/?var=value')
|
||||
|
||||
def test_permanent_redirect(self):
|
||||
"GET a URL that redirects permanently elsewhere"
|
||||
response = self.client.get('/permanent_redirect_view/')
|
||||
# Check that the response was a 301 (permanent redirect)
|
||||
self.assertRedirects(response, 'http://testserver/get_view/', status_code=301)
|
||||
|
||||
client_providing_host = Client(HTTP_HOST='django.testserver')
|
||||
response = client_providing_host.get('/permanent_redirect_view/')
|
||||
# Check that the response was a 301 (permanent redirect) with absolute URI
|
||||
self.assertRedirects(response, 'http://django.testserver/get_view/', status_code=301)
|
||||
self.assertRedirects(response, '/get_view/', status_code=301)
|
||||
|
||||
def test_temporary_redirect(self):
|
||||
"GET a URL that does a non-permanent redirect"
|
||||
response = self.client.get('/temporary_redirect_view/')
|
||||
# Check that the response was a 302 (non-permanent redirect)
|
||||
self.assertRedirects(response, 'http://testserver/get_view/', status_code=302)
|
||||
self.assertRedirects(response, '/get_view/', status_code=302)
|
||||
|
||||
def test_redirect_to_strange_location(self):
|
||||
"GET a URL that redirects to a non-200 page"
|
||||
|
@ -217,12 +204,12 @@ class ClientTest(TestCase):
|
|||
|
||||
# Check that the response was a 302, and that
|
||||
# the attempt to get the redirection location returned 301 when retrieved
|
||||
self.assertRedirects(response, 'http://testserver/permanent_redirect_view/', target_status_code=301)
|
||||
self.assertRedirects(response, '/permanent_redirect_view/', target_status_code=301)
|
||||
|
||||
def test_follow_redirect(self):
|
||||
"A URL that redirects can be followed to termination."
|
||||
response = self.client.get('/double_redirect_view/', follow=True)
|
||||
self.assertRedirects(response, 'http://testserver/get_view/', status_code=302, target_status_code=200)
|
||||
self.assertRedirects(response, '/get_view/', status_code=302, target_status_code=200)
|
||||
self.assertEqual(len(response.redirect_chain), 2)
|
||||
|
||||
def test_redirect_http(self):
|
||||
|
@ -364,7 +351,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Get the page without logging in. Should result in 302.
|
||||
response = self.client.get('/login_protected_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/login_protected_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/login_protected_view/')
|
||||
|
||||
# Log in
|
||||
login = self.client.login(username='testclient', password='password')
|
||||
|
@ -380,7 +367,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Get the page without logging in. Should result in 302.
|
||||
response = self.client.get('/login_protected_method_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/login_protected_method_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/login_protected_method_view/')
|
||||
|
||||
# Log in
|
||||
login = self.client.login(username='testclient', password='password')
|
||||
|
@ -396,7 +383,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Get the page without logging in. Should result in 302.
|
||||
response = self.client.get('/login_protected_view_custom_redirect/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/login_protected_view_custom_redirect/')
|
||||
self.assertRedirects(response, '/accounts/login/?redirect_to=/login_protected_view_custom_redirect/')
|
||||
|
||||
# Log in
|
||||
login = self.client.login(username='testclient', password='password')
|
||||
|
@ -434,7 +421,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Request a page that requires a login
|
||||
response = self.client.get('/login_protected_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/login_protected_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/login_protected_view/')
|
||||
|
||||
@override_settings(SESSION_ENGINE="django.contrib.sessions.backends.signed_cookies")
|
||||
def test_logout_cookie_sessions(self):
|
||||
|
@ -445,7 +432,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Get the page without logging in. Should result in 302.
|
||||
response = self.client.get('/permission_protected_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/permission_protected_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/permission_protected_view/')
|
||||
|
||||
# Log in
|
||||
login = self.client.login(username='testclient', password='password')
|
||||
|
@ -453,7 +440,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Log in with wrong permissions. Should result in 302.
|
||||
response = self.client.get('/permission_protected_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/permission_protected_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/permission_protected_view/')
|
||||
|
||||
# TODO: Log in with right permissions and request the page again
|
||||
|
||||
|
@ -477,7 +464,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Get the page without logging in. Should result in 302.
|
||||
response = self.client.get('/permission_protected_method_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/permission_protected_method_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/permission_protected_method_view/')
|
||||
|
||||
# Log in
|
||||
login = self.client.login(username='testclient', password='password')
|
||||
|
@ -485,7 +472,7 @@ class ClientTest(TestCase):
|
|||
|
||||
# Log in with wrong permissions. Should result in 302.
|
||||
response = self.client.get('/permission_protected_method_view/')
|
||||
self.assertRedirects(response, 'http://testserver/accounts/login/?next=/permission_protected_method_view/')
|
||||
self.assertRedirects(response, '/accounts/login/?next=/permission_protected_method_view/')
|
||||
|
||||
# TODO: Log in with right permissions and request the page again
|
||||
|
||||
|
|
|
@ -18,7 +18,9 @@ from django.test import Client, TestCase, ignore_warnings, override_settings
|
|||
from django.test.client import RedirectCycleError, RequestFactory, encode_file
|
||||
from django.test.utils import ContextList, str_prefix
|
||||
from django.utils._os import upath
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.deprecation import (
|
||||
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||
)
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from .models import CustomUser
|
||||
|
@ -342,12 +344,12 @@ class AssertRedirectsTests(TestCase):
|
|||
try:
|
||||
self.assertRedirects(response, '/get_view/')
|
||||
except AssertionError as e:
|
||||
self.assertIn("Response redirected to 'http://testserver/get_view/?var=value', expected 'http://testserver/get_view/'", str(e))
|
||||
self.assertIn("Response redirected to '/get_view/?var=value', expected '/get_view/'", str(e))
|
||||
|
||||
try:
|
||||
self.assertRedirects(response, '/get_view/', msg_prefix='abc')
|
||||
except AssertionError as e:
|
||||
self.assertIn("abc: Response redirected to 'http://testserver/get_view/?var=value', expected 'http://testserver/get_view/'", str(e))
|
||||
self.assertIn("abc: Response redirected to '/get_view/?var=value', expected '/get_view/'", str(e))
|
||||
|
||||
def test_incorrect_target(self):
|
||||
"An assertion is raised if the response redirects to another target"
|
||||
|
@ -380,7 +382,7 @@ class AssertRedirectsTests(TestCase):
|
|||
status_code=302, target_status_code=200)
|
||||
|
||||
self.assertEqual(len(response.redirect_chain), 1)
|
||||
self.assertEqual(response.redirect_chain[0], ('http://testserver/no_template_view/', 302))
|
||||
self.assertEqual(response.redirect_chain[0], ('/no_template_view/', 302))
|
||||
|
||||
def test_multiple_redirect_chain(self):
|
||||
"You can follow a redirect chain of multiple redirects"
|
||||
|
@ -389,9 +391,9 @@ class AssertRedirectsTests(TestCase):
|
|||
status_code=302, target_status_code=200)
|
||||
|
||||
self.assertEqual(len(response.redirect_chain), 3)
|
||||
self.assertEqual(response.redirect_chain[0], ('http://testserver/redirects/further/', 302))
|
||||
self.assertEqual(response.redirect_chain[1], ('http://testserver/redirects/further/more/', 302))
|
||||
self.assertEqual(response.redirect_chain[2], ('http://testserver/no_template_view/', 302))
|
||||
self.assertEqual(response.redirect_chain[0], ('/redirects/further/', 302))
|
||||
self.assertEqual(response.redirect_chain[1], ('/redirects/further/more/', 302))
|
||||
self.assertEqual(response.redirect_chain[2], ('/no_template_view/', 302))
|
||||
|
||||
def test_redirect_chain_to_non_existent(self):
|
||||
"You can follow a chain to a non-existent view"
|
||||
|
@ -507,21 +509,24 @@ class AssertRedirectsTests(TestCase):
|
|||
def test_redirect_scheme(self):
|
||||
"An assertion is raised if the response doesn't have the scheme specified in expected_url"
|
||||
|
||||
# Assure that original request scheme is preserved if no scheme specified in the redirect location
|
||||
response = self.client.get('/redirect_view/', secure=True)
|
||||
self.assertRedirects(response, 'https://testserver/get_view/')
|
||||
|
||||
# For all possible True/False combinations of follow and secure
|
||||
for follow, secure in itertools.product([True, False], repeat=2):
|
||||
# always redirects to https
|
||||
response = self.client.get('/https_redirect_view/', follow=follow, secure=secure)
|
||||
# no scheme to compare too, always succeeds
|
||||
self.assertRedirects(response, '/secure_view/', status_code=302)
|
||||
# the goal scheme is https
|
||||
self.assertRedirects(response, 'https://testserver/secure_view/', status_code=302)
|
||||
with self.assertRaises(AssertionError):
|
||||
self.assertRedirects(response, 'http://testserver/secure_view/', status_code=302)
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_full_path_in_expected_urls(self):
|
||||
"""
|
||||
Test that specifying a full URL as assertRedirects expected_url still
|
||||
work as backwards compatible behavior until Django 2.1.
|
||||
"""
|
||||
response = self.client.get('/redirect_view/')
|
||||
self.assertRedirects(response, 'http://testserver/get_view/')
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='test_client_regress.urls')
|
||||
class AssertFormErrorTests(TestCase):
|
||||
|
@ -852,7 +857,7 @@ class LoginTests(TestDataMixin, TestCase):
|
|||
# At this points, the self.client isn't logged in.
|
||||
# Check that assertRedirects uses the original client, not the
|
||||
# default client.
|
||||
self.assertRedirects(response, "http://testserver/get_view/")
|
||||
self.assertRedirects(response, "/get_view/")
|
||||
|
||||
|
||||
@override_settings(
|
||||
|
|
|
@ -32,7 +32,6 @@ urlpatterns = [
|
|||
url(r'^accounts/logout/$', auth_views.logout),
|
||||
|
||||
# Special URLs for particular regression cases.
|
||||
url('^中文/$', views.redirect),
|
||||
url('^中文/target/$', views.index_page),
|
||||
]
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class I18NTests(TestCase):
|
|||
for lang_code, lang_name in settings.LANGUAGES:
|
||||
post_data = dict(language=lang_code, next='/')
|
||||
response = self.client.post('/i18n/setlang/', data=post_data)
|
||||
self.assertRedirects(response, 'http://testserver/')
|
||||
self.assertRedirects(response, '/')
|
||||
self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code)
|
||||
|
||||
def test_setlang_unsafe_next(self):
|
||||
|
@ -42,7 +42,7 @@ class I18NTests(TestCase):
|
|||
lang_code, lang_name = settings.LANGUAGES[0]
|
||||
post_data = dict(language=lang_code, next='//unsafe/redirection/')
|
||||
response = self.client.post('/i18n/setlang/', data=post_data)
|
||||
self.assertEqual(response.url, 'http://testserver/')
|
||||
self.assertEqual(response.url, '/')
|
||||
self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], lang_code)
|
||||
|
||||
def test_setlang_reversal(self):
|
||||
|
@ -76,13 +76,13 @@ class I18NTests(TestCase):
|
|||
follow=True, HTTP_REFERER='/en/translated/'
|
||||
)
|
||||
self.assertEqual(self.client.session[LANGUAGE_SESSION_KEY], 'nl')
|
||||
self.assertRedirects(response, 'http://testserver/nl/vertaald/')
|
||||
self.assertRedirects(response, '/nl/vertaald/')
|
||||
# And reverse
|
||||
response = self.client.post(
|
||||
'/i18n/setlang/', data={'language': 'en'},
|
||||
follow=True, HTTP_REFERER='/nl/vertaald/'
|
||||
)
|
||||
self.assertRedirects(response, 'http://testserver/en/translated/')
|
||||
self.assertRedirects(response, '/en/translated/')
|
||||
|
||||
def test_jsi18n(self):
|
||||
"""The javascript_catalog can be deployed with language settings"""
|
||||
|
|
|
@ -11,17 +11,6 @@ class URLHandling(TestCase):
|
|||
"""
|
||||
redirect_target = "/%E4%B8%AD%E6%96%87/target/"
|
||||
|
||||
def test_combining_redirect(self):
|
||||
"""
|
||||
Tests that redirecting to an IRI, requiring encoding before we use it
|
||||
in an HTTP response, is handled correctly. In this case the arg to
|
||||
HttpRedirect is ASCII but the current request path contains non-ASCII
|
||||
characters so this test ensures the creation of the full path with a
|
||||
base non-ASCII part is handled correctly.
|
||||
"""
|
||||
response = self.client.get('/中文/')
|
||||
self.assertRedirects(response, self.redirect_target)
|
||||
|
||||
def test_nonascii_redirect(self):
|
||||
"""
|
||||
Tests that a non-ASCII argument to HttpRedirect is handled properly.
|
||||
|
|
|
@ -6,9 +6,7 @@ import sys
|
|||
|
||||
from django.core.exceptions import PermissionDenied, SuspiciousOperation
|
||||
from django.core.urlresolvers import get_resolver
|
||||
from django.http import (
|
||||
Http404, HttpResponse, HttpResponseRedirect, JsonResponse,
|
||||
)
|
||||
from django.http import Http404, HttpResponse, JsonResponse
|
||||
from django.shortcuts import render, render_to_response
|
||||
from django.template import TemplateDoesNotExist
|
||||
from django.utils.log import getLogger
|
||||
|
@ -71,13 +69,6 @@ class Http404View(View):
|
|||
raise Http404("Testing class-based technical 404.")
|
||||
|
||||
|
||||
def redirect(request):
|
||||
"""
|
||||
Forces an HTTP redirect.
|
||||
"""
|
||||
return HttpResponseRedirect("target/")
|
||||
|
||||
|
||||
def view_exception(request, n):
|
||||
raise BrokenException(except_args[int(n)])
|
||||
|
||||
|
|
Loading…
Reference in New Issue