Skip to content

Proxito: check forced redirects before system redirects#12903

Draft
ericholscher wants to merge 4 commits intomainfrom
fix/forced-redirects-before-system-redirects-10314
Draft

Proxito: check forced redirects before system redirects#12903
ericholscher wants to merge 4 commits intomainfrom
fix/forced-redirects-before-system-redirects-10314

Conversation

@ericholscher
Copy link
Copy Markdown
Member

@ericholscher ericholscher commented Mar 31, 2026

Summary

Forced exact redirects are now checked before system redirects (e.g., //en/latest/) in serve_path(), so users can redirect entire projects to another domain with a single forced redirect rule.

Previously, a request to / would always be system-redirected to /en/latest/ before any user-defined redirects were checked. This meant redirecting an entire project to another domain required creating forced redirects for every system redirect path (/, /en/, /en/latest/, etc.) instead of a single /* rule.

How it works

  • An early forced redirect check runs at the top of serve_path(), before unresolve_path() is called
  • At this point only the raw request path is available (no resolved language/version/filename), so only exact redirects can match — this is intentional and covers the primary use case
  • Page redirects (which need the resolved filename) still use the existing check after path resolution
  • The early check uses the main project from the domain, so a wildcard /* on the main project catches all traffic including translations (/es/...) and subprojects (/projects/subproject/...)
  • Non-forced redirects are unaffected — they still only apply on 404s

Changes

  1. readthedocs/proxito/views/serve.py — Added early forced redirect check before system redirects
  2. readthedocs/proxito/tests/test_old_redirects.py — Added UserForcedRedirectBeforeSystemRedirectTests with 13 tests; updated test_exact_redirect_with_wildcard to expect 302 instead of 404
  3. docs/user/user-defined-redirects.rst — Documented forced redirect ordering in "Limitations and observations" and enhanced the "Migrating to another domain" example

Closes #10314

Test plan

  • 13 tests in UserForcedRedirectBeforeSystemRedirectTests covering:
    • Exact forced redirect from / to external domain
    • Wildcard /* from root and subpaths
    • Translation paths (/es/latest/...) and translation root (/es/)
    • Subproject paths (/projects/subproject/en/latest/...) and subproject root
    • Non-wildcard redirects don't leak into subproject paths
    • Non-forced redirects don't override system redirects
    • Query parameter preservation and 301 status
  • All 82 tests in test_old_redirects.py pass
  • All 23 tests in test_redirects.py pass

Made by AI

Forced exact redirects are now checked before system redirects
(e.g., / -> /en/latest/) so users can redirect entire projects
to another domain with a single redirect rule.

Fixes #10314
Clarify that forced exact redirects are checked before built-in
redirects, so a single rule on /* is sufficient to redirect all
traffic including the root URL, translations, and subprojects.
@read-the-docs-community
Copy link
Copy Markdown

Documentation build overview

📚 docs | 🛠️ Build #32058472 | 📁 Comparing a41cc39 against latest (e3a4d81)


🔍 Preview build

Show files changed (1 files in total): 📝 1 modified | ➕ 0 added | ➖ 0 deleted
File Status
user-defined-redirects.html 📝 modified

Add tests verifying that forced wildcard redirects on the main project
catch translation paths, translation root, subproject paths, and
subproject root before system redirects. Also verify non-wildcard
redirects on the main project do not leak into subproject paths.
When forced redirects fire before URL resolution (the new early check),
set request.path_project_slug and attempt to resolve the path to get
version info for proper CDN cache control and cache tag headers.

If resolution fails (e.g., "/" before system redirect), default to
caching the redirect response since the target URL will handle authz.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Proxito: check for forced redirects before system redirects

1 participant