diff --git a/readthedocs/projects/tasks/search.py b/readthedocs/projects/tasks/search.py index 4168fb61c8d..5e783115e84 100644 --- a/readthedocs/projects/tasks/search.py +++ b/readthedocs/projects/tasks/search.py @@ -203,7 +203,9 @@ 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"]: + # 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) # 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..fe7cdeff889 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_as_index 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_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 + # 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_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 c33a76a3833..98612b0a4c3 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,25 @@ def proxito_404_page_handler( ) r.status_code = http_status return r + + +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) + + # 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, + ]) + # fmt: on