Skip to content

Proxito: use unresolver in 404 handler #10074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions readthedocs/core/unresolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ def __init__(self, project, version_slug, filename):


class TranslationNotFoundError(UnresolverError):
def __init__(self, project, language, filename):
def __init__(self, project, language, filename, version_slug):
self.project = project
self.language = language
self.filename = filename
self.version_slug = version_slug


class InvalidPathForVersionedProjectError(UnresolverError):
Expand Down Expand Up @@ -264,7 +265,10 @@ def _match_multiversion_project(
project = parent_project.translations.filter(language=language).first()
if not project:
raise TranslationNotFoundError(
project=parent_project, language=language, filename=file
project=parent_project,
language=language,
filename=file,
version_slug=version_slug,
)

if external_version_slug and external_version_slug != version_slug:
Expand Down
42 changes: 41 additions & 1 deletion readthedocs/proxito/tests/test_old_redirects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,16 @@ def test_redirect_prefix_crossdomain(self):
self.assertEqual(r.status_code, 302, url)
self.assertEqual(r["Location"], expected_location, url)

# These aren't even handled by Django.
def test_redirect_prefix_crossdomain_with_newline_chars(self):
fixture.get(
Redirect,
project=self.project,
redirect_type="prefix",
from_url="/",
)
# We make use of Django's URL resolve in the current implementation,
# which doesn't handle these chars and raises an exception
# instead of redirecting.
urls = [
# Trying to bypass the protocol check by including a `\n` char.
"http://project.dev.readthedocs.io/http:/%0A/my.host/path.html",
Expand Down Expand Up @@ -1135,3 +1144,34 @@ def setUp(self):
default_true=True,
future_default_true=True,
)

def test_redirect_prefix_crossdomain_with_newline_chars(self):
"""
Overridden to make it compatible with the new implementation.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could also make the old implementation compatible, isn't a lot of code, but I'm not sure if we want to spend more time there... (but kind of already spent time debugging it :_)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The old implementation", is the one we are going to delete, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah


In the new implementation we will correctly redirect,
instead of raising an exception.
"""
fixture.get(
Redirect,
project=self.project,
redirect_type="prefix",
from_url="/",
)
urls = [
(
"http://project.dev.readthedocs.io/http:/%0A/my.host/path.html",
"http://project.dev.readthedocs.io/en/latest/http://my.host/path.html",
),
(
"http://project.dev.readthedocs.io/%0A/my.host/path.html",
"http://project.dev.readthedocs.io/en/latest/my.host/path.html",
),
]
for url, expected_location in urls:
r = self.client.get(
url,
HTTP_HOST="project.dev.readthedocs.io",
)
self.assertEqual(r.status_code, 302, url)
self.assertEqual(r["Location"], expected_location, url)
15 changes: 14 additions & 1 deletion readthedocs/proxito/tests/test_redirects.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Copied from .org test_redirects

from django.test import override_settings
from django_dynamic_fixture import get

from readthedocs.projects.models import Feature
from readthedocs.proxito.constants import RedirectType

from .base import BaseDocServing
Expand Down Expand Up @@ -260,3 +261,15 @@ def test_slash_redirect(self):
# WARNING
# The test client strips multiple slashes at the front of the URL
# Additional tests for this are in ``test_middleware:test_front_slash``


class ProxitoV2RedirectTests(RedirectTests):
# TODO: remove this class once the new implementation is the default.
def setUp(self):
super().setUp()
get(
Feature,
feature_id=Feature.USE_UNRESOLVER_WITH_PROXITO,
default_true=True,
future_default_true=True,
)
17 changes: 16 additions & 1 deletion readthedocs/proxito/tests/test_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
"""Test URL config."""

import pytest
from django.test import TestCase, override_settings
from django.test import TestCase
from django.urls import resolve
from django_dynamic_fixture import get

from readthedocs.projects.models import Feature


@pytest.mark.proxito
Expand Down Expand Up @@ -103,3 +106,15 @@ def test_single_version(self):
'filename': 'some/path/index.html',
},
)


class ProxitoV2TestSingleVersionURLs(TestSingleVersionURLs):
# TODO: remove this class once the new implementation is the default.
def setUp(self):
super().setUp()
get(
Feature,
feature_id=Feature.USE_UNRESOLVER_WITH_PROXITO,
default_true=True,
future_default_true=True,
)
Loading