Skip to content

Commit cac4fcc

Browse files
authored
Merge pull request #4833 from rtfd/humitos/redirects/avoid-infinite
Avoid infinite redirection
2 parents cb215c2 + 00fe39a commit cac4fcc

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

readthedocs/core/views/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,16 @@ def server_error_404(request, exception=None, template_name='404.html'): # pyli
116116
Marking exception as optional to make /404/ testing page to work.
117117
"""
118118
response = get_redirect_response(request, path=request.get_full_path())
119+
119120
if response:
120-
return response
121+
if response.url == request.build_absolute_uri():
122+
# check that we do have a response and avoid infinite redirect
123+
log.warning(
124+
'Infinite Redirect: FROM URL is the same than TO URL. url=%s',
125+
response.url,
126+
)
127+
else:
128+
return response
121129
r = render(request, template_name)
122130
r.status_code = 404
123131
return r

readthedocs/rtd_tests/tests/test_redirects.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,34 @@ def setUp(self):
127127
self.pip = Project.objects.get(slug='pip')
128128
self.pip.versions.create_latest()
129129

130+
@override_settings(USE_SUBDOMAIN=True)
131+
def test_redirect_prefix_infinite(self):
132+
"""
133+
Avoid infinite redirects.
134+
135+
If the URL hit is the same that the URL returned for redirection, we
136+
return a 404.
137+
138+
These examples comes from this issue:
139+
* https://github.com/rtfd/readthedocs.org/issues/4673
140+
"""
141+
Redirect.objects.create(
142+
project=self.pip, redirect_type='prefix',
143+
from_url='/',
144+
)
145+
r = self.client.get('/redirect', HTTP_HOST='pip.readthedocs.org')
146+
self.assertEqual(r.status_code, 302)
147+
self.assertEqual(
148+
r['Location'], 'http://pip.readthedocs.org/en/latest/redirect.html')
149+
150+
r = self.client.get('/redirect/', HTTP_HOST='pip.readthedocs.org')
151+
self.assertEqual(r.status_code, 302)
152+
self.assertEqual(
153+
r['Location'], 'http://pip.readthedocs.org/en/latest/redirect/')
154+
155+
r = self.client.get('/en/latest/redirect/', HTTP_HOST='pip.readthedocs.org')
156+
self.assertEqual(r.status_code, 404)
157+
130158
@override_settings(USE_SUBDOMAIN=True)
131159
def test_redirect_root(self):
132160
Redirect.objects.create(

0 commit comments

Comments
 (0)