-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Redirects: allow to redirect even if a page exists #9243
Conversation
a4ed43f
to
266284c
Compare
266284c
to
6b8f556
Compare
Features | ||
-------- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't sure about where to describe this option,
also the mention of redirect to external sites doesn't look like a limitation :D
# TODO: remove after migration. | ||
self.fields["force"].widget = forms.CheckboxInput() | ||
self.fields["force"].empty_value = False |
There was a problem hiding this comment.
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 field non-nullable and just deal with a couple of minutes of users no being able to create redirects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No strong preference here, but being safe seems fine.
# ) | ||
# if redirect_path and http_status: | ||
# return self.get_redirect_response(request, redirect_path, http_status) | ||
redirect_path, http_status = self.get_redirect( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could just call final_project.get_redirect_path_with_status()
directly, we aren't adding anything extra on get_redirect
.
# ``redirect_filename`` is the path without ``/<lang>/<version>`` and | ||
# without query, starting with a ``/``. This matches our old logic: | ||
# https://github.com/readthedocs/readthedocs.org/blob/4b09c7a0ab45cd894c3373f7f07bad7161e4b223/readthedocs/redirects/utils.py#L60 # noqa | ||
# | ||
# We parse ``filename`` to: | ||
# - Remove the query params (probably it doesn't contain any query params at this point) | ||
# - Remove any invalid URL chars (\r, \n, \t). | ||
# | ||
# We don't use ``.path`` to avoid parsing the filename as a full url. | ||
# For example if the filename is ``http://example.com/my-path``, | ||
# ``.path`` would return ``my-path``. | ||
parsed = urlparse(filename) | ||
redirect_filename = parsed._replace(query="").geturl() | ||
|
||
# We can't check for lang and version here to decide if we need to add | ||
# the ``/`` or not because ``/install.html`` is a valid path to use as | ||
# redirect and does not include lang and version on it. It should be | ||
# fine always adding the ``/`` to the beginning. | ||
redirect_filename = '/' + redirect_filename.lstrip('/') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was moved to the get_redirect_path_with_status method itself
full_path=proxito_path, | ||
) | ||
return resp | ||
|
||
self._register_broken_link( | ||
project=final_project, | ||
version=version, | ||
path=redirect_filename, | ||
path=filename, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already normalize the filename before recording the broken link, so we are fine using the original filename
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks straightforward. I'd like to get it deployed so we can test it out for performance. I think it's probably going to be painful, but it's useful to have if we need it for a user, for now.
@@ -128,6 +130,17 @@ Similarly, if you maintain several branches of your documentation (e.g. ``3.0`` | |||
``latest``) and decide to move pages in ``latest`` but not the older branches, you can use | |||
*Exact Redirects* to do so. | |||
|
|||
You can use an exact redirect to migrate your documentation to another domain, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section needs some subsections. There's a lot of content here, I think a few subsections would make it easier to follow. Probably headers with what each example is doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have put the examples in subsections.
There is a lot of nesting, maybe we could address a more structural change as part of #9258
# TODO: remove after migration. | ||
self.fields["force"].widget = forms.CheckboxInput() | ||
self.fields["force"].empty_value = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No strong preference here, but being safe seems fine.
http_status=http_status, | ||
) | ||
except InfiniteRedirectException: | ||
# Continue with our normal serve. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we log something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already log that here
readthedocs.org/readthedocs/proxito/views/mixins.py
Lines 248 to 254 in 0acd5e4
if from_url == to: | |
# check that we do have a response and avoid infinite redirect | |
log.warning( | |
'Infinite Redirect: FROM URL is the same than TO URL.', | |
url=to, | |
) | |
raise InfiniteRedirectException() |
but we can add another here to be more specific
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add force=
attribute to that log line (or to log.bind
when it's called originally) to have more context when debugging.
readthedocs/redirects/querysets.py
Outdated
if forced_only and not self.filter(force=True).exists(): | ||
return None, None | ||
|
||
def normalize_path(path): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This inline function feels a bit weird.. Is there a reason it isn't in a utils file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it was very specific to this method, I'll move it to be a private method
Netify call this option "force", I think it is okay to call them that way in our platform.