Fixed #32790 -- Ensured test Client handles redirects to domain indexes without a specified trailing slash.

This commit is contained in:
tomhamiltonstubber 2021-05-27 11:44:42 +02:00 committed by Carlton Gibson
parent d54059ebce
commit 1e5aa8e1c7
4 changed files with 26 additions and 2 deletions

View File

@ -834,7 +834,7 @@ class Client(ClientMixin, RequestFactory):
extra['SERVER_PORT'] = str(url.port) extra['SERVER_PORT'] = str(url.port)
# Prepend the request path to handle relative path redirects # Prepend the request path to handle relative path redirects
path = url.path path = url.path or '/'
if not path.startswith('/'): if not path.startswith('/'):
path = urljoin(response.request['PATH_INFO'], path) path = urljoin(response.request['PATH_INFO'], path)

View File

@ -762,6 +762,13 @@ class ClientTest(TestCase):
response = self.client.get('/django_project_redirect/') response = self.client.get('/django_project_redirect/')
self.assertRedirects(response, 'https://www.djangoproject.com/', fetch_redirect_response=False) self.assertRedirects(response, 'https://www.djangoproject.com/', fetch_redirect_response=False)
def test_external_redirect_without_trailing_slash(self):
"""
Client._handle_redirects() with an empty path.
"""
response = self.client.get('/no_trailing_slash_external_redirect/', follow=True)
self.assertRedirects(response, 'https://testserver')
def test_external_redirect_with_fetch_error_msg(self): def test_external_redirect_with_fetch_error_msg(self):
""" """
assertRedirects without fetch_redirect_response=False raises assertRedirects without fetch_redirect_response=False raises

View File

@ -46,8 +46,9 @@ urlpatterns = [
path('mass_mail_sending_view/', views.mass_mail_sending_view), path('mass_mail_sending_view/', views.mass_mail_sending_view),
path('nesting_exception_view/', views.nesting_exception_view), path('nesting_exception_view/', views.nesting_exception_view),
path('django_project_redirect/', views.django_project_redirect), path('django_project_redirect/', views.django_project_redirect),
path('no_trailing_slash_external_redirect/', views.no_trailing_slash_external_redirect),
path('', views.index_view, name='index'), # Target for no_trailing_slash_external_redirect/ with follow=True
path('two_arg_exception/', views.two_arg_exception), path('two_arg_exception/', views.two_arg_exception),
path('accounts/', RedirectView.as_view(url='login/')), path('accounts/', RedirectView.as_view(url='login/')),
path('accounts/no_trailing_slash', RedirectView.as_view(url='login/')), path('accounts/no_trailing_slash', RedirectView.as_view(url='login/')),
path('accounts/login/', auth_views.LoginView.as_view(template_name='login.html')), path('accounts/login/', auth_views.LoginView.as_view(template_name='login.html')),

View File

@ -381,6 +381,22 @@ def django_project_redirect(request):
return HttpResponseRedirect('https://www.djangoproject.com/') return HttpResponseRedirect('https://www.djangoproject.com/')
def no_trailing_slash_external_redirect(request):
"""
RFC 2616 3.2.2: A bare domain without any abs_path element should be
treated as having the trailing `/`.
Use https://testserver, rather than an external domain, in order to allow
use of follow=True, triggering Client._handle_redirects().
"""
return HttpResponseRedirect('https://testserver')
def index_view(request):
"""Target for no_trailing_slash_external_redirect with follow=True."""
return HttpResponse('Hello world')
def upload_view(request): def upload_view(request):
"""Prints keys of request.FILES to the response.""" """Prints keys of request.FILES to the response."""
return HttpResponse(', '.join(request.FILES)) return HttpResponse(', '.join(request.FILES))