From 88f58bf9a489156d445c083a8db0473103b075ae Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Thu, 23 May 2024 18:45:32 +0200 Subject: [PATCH 1/4] Proxito: browndate for redirecting `/` to `README.html` Related https://github.com/readthedocs/readthedocs.org/issues/9993 --- readthedocs/projects/tasks/search.py | 8 +++++++- readthedocs/proxito/views/serve.py | 19 ++++++++++++------- readthedocs/proxito/views/utils.py | 23 +++++++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/readthedocs/projects/tasks/search.py b/readthedocs/projects/tasks/search.py index 4168fb61c8d..7e6ffc6977e 100644 --- a/readthedocs/projects/tasks/search.py +++ b/readthedocs/projects/tasks/search.py @@ -6,6 +6,7 @@ from readthedocs.builds.models import Build, Version from readthedocs.projects.models import HTMLFile, Project from readthedocs.projects.signals import files_changed +from readthedocs.proxito.views.utils import allow_readme_html_at_root_url from readthedocs.search.documents import PageDocument from readthedocs.search.utils import index_objects, remove_indexed_files from readthedocs.storage import build_media_storage @@ -203,7 +204,12 @@ def _create_imported_files_and_search_index( # Create the imported file only if it's a top-level 404 file, # or if it's an index file. We don't need to keep track of all files. - if relpath == "404.html" or filename in ["index.html", "README.html"]: + if allow_readme_html_at_root_url(): + tryfiles = ["index.html", "README.html"] + else: + tryfiles = ["index.html"] + + if relpath == "404.html" or filename in tryfiles: html_files_to_save.append(html_file) # We first index the files in ES, and then save the objects in the DB. diff --git a/readthedocs/proxito/views/serve.py b/readthedocs/proxito/views/serve.py index 4f44d51fa07..4d81916df64 100644 --- a/readthedocs/proxito/views/serve.py +++ b/readthedocs/proxito/views/serve.py @@ -41,6 +41,7 @@ ServeRedirectMixin, StorageFileNotFound, ) +from readthedocs.proxito.views.utils import allow_readme_html_at_root_url from readthedocs.redirects.exceptions import InfiniteRedirectException from readthedocs.storage import build_media_storage @@ -641,12 +642,16 @@ def _get_index_file_redirect(self, request, project, version, filename, full_pat - /en/latest/foo -> /en/latest/foo/README.html - /en/latest/foo/ -> /en/latest/foo/README.html """ - tryfiles = ["index.html", "README.html"] - # If the path ends with `/`, we already tried to serve - # the `/index.html` file, so we only need to test for - # the `/README.html` file. - if full_path.endswith("/"): - tryfiles = ["README.html"] + + if allow_readme_html_at_root_url(): + tryfiles = ["index.html", "README.html"] + # If the path ends with `/`, we already tried to serve + # the `/index.html` file, so we only need to test for + # the `/README.html` file. + if full_path.endswith("/"): + tryfiles = ["README.html"] + else: + tryfiles = ["index.html"] tryfiles = [ (filename.rstrip("/") + f"/{tryfile}").lstrip("/") for tryfile in tryfiles @@ -664,7 +669,7 @@ def _get_index_file_redirect(self, request, project, version, filename, full_pat log.info("Redirecting to index file.", tryfile=tryfile) # Use urlparse so that we maintain GET args in our redirect parts = urlparse(full_path) - if tryfile.endswith("README.html"): + if allow_readme_html_at_root_url() and tryfile.endswith("README.html"): new_path = parts.path.rstrip("/") + "/README.html" else: new_path = parts.path.rstrip("/") + "/" diff --git a/readthedocs/proxito/views/utils.py b/readthedocs/proxito/views/utils.py index c33a76a3833..e301aed4c48 100644 --- a/readthedocs/proxito/views/utils.py +++ b/readthedocs/proxito/views/utils.py @@ -1,4 +1,8 @@ +import datetime + +import pytz import structlog +from django.conf import settings from django.http import HttpResponse from django.shortcuts import render @@ -56,3 +60,22 @@ def proxito_404_page_handler( ) r.status_code = http_status return r + + +def allow_readme_html_at_root_url(): + tzinfo = pytz.timezone("America/Los_Angeles") + now = datetime.datetime.now(tz=tzinfo) + + # Brownout dates as published in https://about.readthedocs.com/blog/2024/05/readme-html-deprecated/ + # fmt: off + return not any([ + # 12 hours browndate + datetime.datetime(2024, 6, 10, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 6, 10, 12, 0, 0, tzinfo=tzinfo), + # 24 hours browndate + datetime.datetime(2024, 6, 17, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 6, 18, 0, 0, 0, tzinfo=tzinfo), + # 48 hours browndate + datetime.datetime(2024, 6, 24, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 6, 26, 0, 0, 0, tzinfo=tzinfo), + # Deprecated after July 1st + datetime.datetime(2024, 7, 1, 0, 0, 0, tzinfo=tzinfo) < now, + ]) and settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS + # fmt: on From 91619679cfb2dbdb55aada54aac4fb114a286c9b Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Fri, 24 May 2024 17:36:33 +0200 Subject: [PATCH 2/4] Rename function to make it clearer --- readthedocs/projects/tasks/search.py | 4 ++-- readthedocs/proxito/views/serve.py | 6 +++--- readthedocs/proxito/views/utils.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/readthedocs/projects/tasks/search.py b/readthedocs/projects/tasks/search.py index 7e6ffc6977e..85c31c20ace 100644 --- a/readthedocs/projects/tasks/search.py +++ b/readthedocs/projects/tasks/search.py @@ -6,7 +6,7 @@ from readthedocs.builds.models import Build, Version from readthedocs.projects.models import HTMLFile, Project from readthedocs.projects.signals import files_changed -from readthedocs.proxito.views.utils import allow_readme_html_at_root_url +from readthedocs.proxito.views.utils import allow_readme_html_as_index from readthedocs.search.documents import PageDocument from readthedocs.search.utils import index_objects, remove_indexed_files from readthedocs.storage import build_media_storage @@ -204,7 +204,7 @@ def _create_imported_files_and_search_index( # Create the imported file only if it's a top-level 404 file, # or if it's an index file. We don't need to keep track of all files. - if allow_readme_html_at_root_url(): + if allow_readme_html_as_index(): tryfiles = ["index.html", "README.html"] else: tryfiles = ["index.html"] diff --git a/readthedocs/proxito/views/serve.py b/readthedocs/proxito/views/serve.py index 4d81916df64..fe7cdeff889 100644 --- a/readthedocs/proxito/views/serve.py +++ b/readthedocs/proxito/views/serve.py @@ -41,7 +41,7 @@ ServeRedirectMixin, StorageFileNotFound, ) -from readthedocs.proxito.views.utils import allow_readme_html_at_root_url +from readthedocs.proxito.views.utils import allow_readme_html_as_index from readthedocs.redirects.exceptions import InfiniteRedirectException from readthedocs.storage import build_media_storage @@ -643,7 +643,7 @@ def _get_index_file_redirect(self, request, project, version, filename, full_pat - /en/latest/foo/ -> /en/latest/foo/README.html """ - if allow_readme_html_at_root_url(): + if allow_readme_html_as_index(): tryfiles = ["index.html", "README.html"] # If the path ends with `/`, we already tried to serve # the `/index.html` file, so we only need to test for @@ -669,7 +669,7 @@ def _get_index_file_redirect(self, request, project, version, filename, full_pat log.info("Redirecting to index file.", tryfile=tryfile) # Use urlparse so that we maintain GET args in our redirect parts = urlparse(full_path) - if allow_readme_html_at_root_url() and tryfile.endswith("README.html"): + if allow_readme_html_as_index() and tryfile.endswith("README.html"): new_path = parts.path.rstrip("/") + "/README.html" else: new_path = parts.path.rstrip("/") + "/" diff --git a/readthedocs/proxito/views/utils.py b/readthedocs/proxito/views/utils.py index e301aed4c48..4e804c9dcd5 100644 --- a/readthedocs/proxito/views/utils.py +++ b/readthedocs/proxito/views/utils.py @@ -62,7 +62,7 @@ def proxito_404_page_handler( return r -def allow_readme_html_at_root_url(): +def allow_readme_html_as_index(): tzinfo = pytz.timezone("America/Los_Angeles") now = datetime.datetime.now(tz=tzinfo) From df3df02980c3ab61ded43dba299f1372594a2986 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 28 May 2024 17:55:38 +0200 Subject: [PATCH 3/4] Keep indexing README.html for now --- readthedocs/projects/tasks/search.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/readthedocs/projects/tasks/search.py b/readthedocs/projects/tasks/search.py index 85c31c20ace..5e783115e84 100644 --- a/readthedocs/projects/tasks/search.py +++ b/readthedocs/projects/tasks/search.py @@ -6,7 +6,6 @@ from readthedocs.builds.models import Build, Version from readthedocs.projects.models import HTMLFile, Project from readthedocs.projects.signals import files_changed -from readthedocs.proxito.views.utils import allow_readme_html_as_index from readthedocs.search.documents import PageDocument from readthedocs.search.utils import index_objects, remove_indexed_files from readthedocs.storage import build_media_storage @@ -204,11 +203,8 @@ def _create_imported_files_and_search_index( # Create the imported file only if it's a top-level 404 file, # or if it's an index file. We don't need to keep track of all files. - if allow_readme_html_as_index(): - tryfiles = ["index.html", "README.html"] - else: - tryfiles = ["index.html"] - + # TODO: delete README.html from this list after deprecation. + tryfiles = ["index.html", "README.html"] if relpath == "404.html" or filename in tryfiles: html_files_to_save.append(html_file) From a91707ae55ba1a1f3517c90275c3e2d6689b1ffb Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Tue, 28 May 2024 18:38:30 +0200 Subject: [PATCH 4/4] Update logic to take into account enforce brownout setting --- readthedocs/proxito/views/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/readthedocs/proxito/views/utils.py b/readthedocs/proxito/views/utils.py index 4e804c9dcd5..98612b0a4c3 100644 --- a/readthedocs/proxito/views/utils.py +++ b/readthedocs/proxito/views/utils.py @@ -63,6 +63,9 @@ def proxito_404_page_handler( def allow_readme_html_as_index(): + if not settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS: + return True + tzinfo = pytz.timezone("America/Los_Angeles") now = datetime.datetime.now(tz=tzinfo) @@ -77,5 +80,5 @@ def allow_readme_html_as_index(): datetime.datetime(2024, 6, 24, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 6, 26, 0, 0, 0, tzinfo=tzinfo), # Deprecated after July 1st datetime.datetime(2024, 7, 1, 0, 0, 0, tzinfo=tzinfo) < now, - ]) and settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS + ]) # fmt: on