From 1e5aa8e1c79252cc810af21294a6e945d11d37b3 Mon Sep 17 00:00:00 2001 From: tomhamiltonstubber Date: Thu, 27 May 2021 11:44:42 +0200 Subject: [PATCH] Fixed #32790 -- Ensured test Client handles redirects to domain indexes without a specified trailing slash. --- django/test/client.py | 2 +- tests/test_client/tests.py | 7 +++++++ tests/test_client/urls.py | 3 ++- tests/test_client/views.py | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/django/test/client.py b/django/test/client.py index 00c949ce58..4a0b6b45f4 100644 --- a/django/test/client.py +++ b/django/test/client.py @@ -834,7 +834,7 @@ class Client(ClientMixin, RequestFactory): extra['SERVER_PORT'] = str(url.port) # Prepend the request path to handle relative path redirects - path = url.path + path = url.path or '/' if not path.startswith('/'): path = urljoin(response.request['PATH_INFO'], path) diff --git a/tests/test_client/tests.py b/tests/test_client/tests.py index 6156a1ddbc..a808cc9763 100644 --- a/tests/test_client/tests.py +++ b/tests/test_client/tests.py @@ -762,6 +762,13 @@ class ClientTest(TestCase): response = self.client.get('/django_project_redirect/') 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): """ assertRedirects without fetch_redirect_response=False raises diff --git a/tests/test_client/urls.py b/tests/test_client/urls.py index 1bc552ba5d..e2275797af 100644 --- a/tests/test_client/urls.py +++ b/tests/test_client/urls.py @@ -46,8 +46,9 @@ urlpatterns = [ path('mass_mail_sending_view/', views.mass_mail_sending_view), path('nesting_exception_view/', views.nesting_exception_view), 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('accounts/', 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')), diff --git a/tests/test_client/views.py b/tests/test_client/views.py index 3ac0e57976..692581e892 100644 --- a/tests/test_client/views.py +++ b/tests/test_client/views.py @@ -381,6 +381,22 @@ def django_project_redirect(request): 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): """Prints keys of request.FILES to the response.""" return HttpResponse(', '.join(request.FILES))