Skip to content

Commit 889e9d1

Browse files
authored
Proxito: always check 404/index.hmtml (#9983)
* Proxito: always check `404/index.hmtml` With the introduction of `build.commands` we cannot use `version.documentation_type` anymore since those versions will be `generic` and we can't skip checking for this file location. Note this commit may add and extra call to S3 API for all the 404 pages where our regular Maze will be shown. However, it removes 2 databsae calls from all the 404 requests. We could only add this extra check on S3 for `version.documentation_type='generic'`, but that would make the code a little more complex and we won't be removing these 2 db queries. Reference: readthedocs/sphinx-notfound-page#215 (comment) * Docs: mention `404/index.html` in hosting docs * Proxito: get the `Version` from inside `register_page_view` * Proxit: get the version after checking for bot score * Proxit: call `register_page_view` just once * Log: index file (`index.html` or `README.html`) I'm interested in `README.html` since we should probably deprecate that "feature" * Tests: add extra checks to make tests pass * Lint
1 parent e85ee7d commit 889e9d1

File tree

3 files changed

+44
-51
lines changed

3 files changed

+44
-51
lines changed

docs/user/hosting.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,18 @@ Custom Not Found (404) Pages
7474
----------------------------
7575

7676
If you want your project to use a custom page for not found pages instead of the "Maze Found" default,
77-
you can put a ``404.html`` at the top level of your project's HTML output.
77+
you can put a ``404.html`` or ``404/index.html`` in your project's HTML output.
7878

7979
When a 404 is returned,
80-
Read the Docs checks if there is a ``404.html`` in the root of your project's output
80+
Read the Docs checks if there is a ``404.html`` or ``404/index.html`` in your project's output
8181
corresponding to the *current* version
8282
and uses it if it exists.
83-
Otherwise, it tries to fall back to the ``404.html`` page
83+
Otherwise, it tries to fall back to the ``404.html`` or ``404/index.html`` page
8484
corresponding to the *default* version of the project.
8585

8686
We recommend the `sphinx-notfound-page`_ extension,
8787
which Read the Docs maintains.
88-
It automatically creates a ``404.html`` page for your documentation,
88+
It automatically creates a the 404 page for your documentation,
8989
matching the theme of your project.
9090
See its documentation_ for how to install and customize it.
9191

readthedocs/proxito/tests/test_full.py

+20-13
Original file line numberDiff line numberDiff line change
@@ -819,8 +819,10 @@ def test_404_all_paths_checked_sphinx(self, storage_exists, storage_open):
819819
)
820820
storage_exists.assert_has_calls(
821821
[
822-
mock.call('html/project/fancy-version/404.html'),
823-
mock.call('html/project/latest/404.html'),
822+
mock.call("html/project/fancy-version/404.html"),
823+
mock.call("html/project/fancy-version/404/index.html"),
824+
mock.call("html/project/latest/404.html"),
825+
mock.call("html/project/latest/404/index.html"),
824826
]
825827
)
826828

@@ -848,8 +850,10 @@ def test_404_all_paths_checked_sphinx_single_html(self, storage_exists, storage_
848850
)
849851
storage_exists.assert_has_calls(
850852
[
851-
mock.call('html/project/fancy-version/404.html'),
852-
mock.call('html/project/latest/404.html'),
853+
mock.call("html/project/fancy-version/404.html"),
854+
mock.call("html/project/fancy-version/404/index.html"),
855+
mock.call("html/project/latest/404.html"),
856+
mock.call("html/project/latest/404/index.html"),
853857
]
854858
)
855859

@@ -908,10 +912,12 @@ def test_404_all_paths_checked_mkdocs(self,storage_exists):
908912
)
909913
storage_exists.assert_has_calls(
910914
[
911-
mock.call('html/project/fancy-version/not-found/index.html'),
912-
mock.call('html/project/fancy-version/not-found/README.html'),
913-
mock.call('html/project/fancy-version/404.html'),
914-
mock.call('html/project/latest/404.html')
915+
mock.call("html/project/fancy-version/not-found/index.html"),
916+
mock.call("html/project/fancy-version/not-found/README.html"),
917+
mock.call("html/project/fancy-version/404.html"),
918+
mock.call("html/project/fancy-version/404/index.html"),
919+
mock.call("html/project/latest/404.html"),
920+
mock.call("html/project/latest/404/index.html"),
915921
]
916922
)
917923

@@ -938,11 +944,12 @@ def test_404_all_paths_checked_default_version_different_doc_type(self, storage_
938944
)
939945
storage_exists.assert_has_calls(
940946
[
941-
mock.call('html/project/fancy-version/not-found/index.html'),
942-
mock.call('html/project/fancy-version/not-found/README.html'),
943-
mock.call('html/project/fancy-version/404.html'),
944-
mock.call('html/project/latest/404.html'),
945-
mock.call('html/project/latest/404/index.html'),
947+
mock.call("html/project/fancy-version/not-found/index.html"),
948+
mock.call("html/project/fancy-version/not-found/README.html"),
949+
mock.call("html/project/fancy-version/404.html"),
950+
mock.call("html/project/fancy-version/404/index.html"),
951+
mock.call("html/project/latest/404.html"),
952+
mock.call("html/project/latest/404/index.html"),
946953
]
947954
)
948955

readthedocs/proxito/views/serve.py

+20-34
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from readthedocs.core.resolver import resolve_path
2020
from readthedocs.core.utils.extend import SettingsOverrideObject
2121
from readthedocs.projects import constants
22-
from readthedocs.projects.constants import SPHINX_HTMLDIR
2322
from readthedocs.projects.models import Feature
2423
from readthedocs.projects.templatetags.projects_tags import sort_version_aware
2524
from readthedocs.redirects.exceptions import InfiniteRedirectException
@@ -306,7 +305,7 @@ def get(self, request, proxito_path, template_name='404.html'):
306305
)
307306
log.debug("Trying index filename.")
308307
if build_media_storage.exists(storage_filename_path):
309-
log.info("Redirecting to index file.")
308+
log.info("Redirecting to index file.", tryfile=tryfile)
310309
# Use urlparse so that we maintain GET args in our redirect
311310
parts = urlparse(proxito_path)
312311
if tryfile == "README.html":
@@ -344,27 +343,30 @@ def get(self, request, proxito_path, template_name='404.html'):
344343
# Continue with our normal 404 handling in this case
345344
pass
346345

347-
# If that doesn't work, attempt to serve the 404 of the current version (version_slug)
348-
# Secondly, try to serve the 404 page for the default version
346+
version = Version.objects.filter(
347+
project=final_project, slug=version_slug
348+
).first()
349+
350+
# If there are no redirect,
351+
# try to serve the custom 404 of the current version (version_slug)
352+
# Then, try to serve the custom 404 page for the default version
349353
# (project.get_default_version())
350-
version = (
351-
Version.objects.filter(project=final_project, slug=version_slug)
352-
.only("documentation_type")
353-
.first()
354-
)
355354
versions = []
356355
if version:
357-
versions.append((version.slug, version.documentation_type))
356+
versions.append(version_slug)
358357
default_version_slug = final_project.get_default_version()
359358
if default_version_slug != version_slug:
360-
default_version_doc_type = (
361-
Version.objects.filter(project=final_project, slug=default_version_slug)
362-
.values_list('documentation_type', flat=True)
363-
.first()
364-
)
365-
versions.append((default_version_slug, default_version_doc_type))
359+
versions.append(default_version_slug)
366360

367-
for version_slug_404, doc_type_404 in versions:
361+
# Register 404 pages into our database for user's analytics
362+
self._register_broken_link(
363+
project=final_project,
364+
version=version,
365+
path=filename,
366+
full_path=proxito_path,
367+
)
368+
369+
for version_slug_404 in versions:
368370
if not self.allowed_user(request, final_project, version_slug_404):
369371
continue
370372

@@ -374,11 +376,7 @@ def get(self, request, proxito_path, template_name='404.html'):
374376
include_file=False,
375377
version_type=self.version_type,
376378
)
377-
tryfiles = ['404.html']
378-
# SPHINX_HTMLDIR is the only builder
379-
# that could output a 404/index.html file.
380-
if doc_type_404 == SPHINX_HTMLDIR:
381-
tryfiles.append('404/index.html')
379+
tryfiles = ["404.html", "404/index.html"]
382380
for tryfile in tryfiles:
383381
storage_filename_path = build_media_storage.join(storage_root_path, tryfile)
384382
if build_media_storage.exists(storage_filename_path):
@@ -389,20 +387,8 @@ def get(self, request, proxito_path, template_name='404.html'):
389387
)
390388
resp = HttpResponse(build_media_storage.open(storage_filename_path).read())
391389
resp.status_code = 404
392-
self._register_broken_link(
393-
project=final_project,
394-
version=version,
395-
path=filename,
396-
full_path=proxito_path,
397-
)
398390
return resp
399391

400-
self._register_broken_link(
401-
project=final_project,
402-
version=version,
403-
path=filename,
404-
full_path=proxito_path,
405-
)
406392
raise Http404('No custom 404 page found.')
407393

408394
def _register_broken_link(self, project, version, path, full_path):

0 commit comments

Comments
 (0)