☰
Read the Docs 用户自定义重定向(User-Defined Redirects)完全指南:URL 迁移、版本跳转与内置跳转机制详解
2026/9/27 21:49:28 网站建设 项目流程
  • 后端
  • 文档

【免费下载链接】readthedocs.org

The source code that powers readthedocs.org

项目地址:https://gitcode.com/gh_mirrors/re/readthedocs.org
点击查看免费下载

重定向(Redirect)是 Read the Docs 中保证文档 URL 长期稳定、避免读者遭遇 404 的关键机制。本文以 docs/user/user-defined-redirects.rst 为骨架,结合仓库中readthedocs/redirects与readthedocs/proxito的源码实现,系统讲解内置重定向与用户自定义重定向的四种类型、全部配置参数、限制条件与九个实战示例。读完本文,你将能够熟练在项目仪表盘中配置页面重定向、精确重定向、Clean/HTML URL 互转重定向,并用通配符与:splat占位符完成目录迁移、旧版本弃用、整站换域名等场景。

为什么要管理 URL 结构

随着时间的推移,文档项目常常需要重命名页面、移动内容、调整目录结构。如果放任 URL 结构变化而不做任何处理,用户最终会不断遇到 404 File Not Found 错误。虽然某些场景下 404 可以接受,但糟糕的用户体验通常应当尽量避免。

Read the Docs 提供两层重定向能力:

  • 内置重定向(Built-in redirects):对所有项目自动生效,适合创建和分享指向文档的长期外部链接;
  • 用户自定义重定向(User-defined redirects):由项目维护者自行配置,用于在文档内部移动内容时平滑过渡。

相关的最佳实践可参考 外部链接处理指南(关于创建和处理外部引用)、内容废弃指南(关于废弃文档中的功能与其他主题),以及配套的图文实操指南。

内置重定向:自动生效的四种跳转

内置重定向由 Read the Docs 服务器自动处理,无需任何配置,适用于所有项目。

/page/页面重定向:指向永远最新的页面链接

你可以通过/page/URL 前缀链接到某个具体页面,该链接会自动跳转到你的**默认版本(default version)**下的对应页面。这让外部来源的链接始终保持最新:

https://docs.readthedocs.io/page/guides/best-practice/links.html

另一种做法是使用latest版本:把latest版本固定到某个具体版本上,然后始终链接到latest,例如https://docs.readthedocs.io/en/latest/guides/best-practice/links.html。

/根 URL 重定向:指向默认版本

指向文档根路径的链接(<slug>.readthedocs.io/)会重定向到项目设置中指定的默认版本(default version)。该机制同时适用于 readthedocs.io(Read the Docs Community)、readthedocs-hosted.com(Read the Docs for Business)以及自定义域名:

docs.readthedocs.io -> docs.readthedocs.io/en/stable/

默认版本通常对应项目最近一次正式发布(release)。

警告:根 URL 重定向不能用于引用具体页面。/只重定向到默认版本,而/some/page.html不会重定向到/en/latest/some/page.html。如需页面级跳转,请使用上面的/page/重定向。

/<lang>/语言根重定向:指向该语言的默认版本

指向文档语言根路径的链接(<slug>.readthedocs.io/en/)会重定向到该语言的默认版本。例如访问项目的英文根路径会跳转到其默认版本(stable):

https://docs.readthedocs.io/en/ -> https://docs.readthedocs.io/en/stable/

rtfd.io短链接:便于输入

https://<slug>.rtfd.io形式的链接与readthedocs.io域名的处理方式完全相同,设计目的是方便用户输入、更短更易记,例如https://docs.rtfd.io。

这些内置跳转在源码中由ServeRedirectMixin.system_redirect(见 readthedocs/proxito/views/mixins.py)统一实现:它负责/与/page/*等由平台定义的系统级跳转,通过Resolver().resolve(...)计算出目标地址,并在响应头中写入X-RTD-Redirect: system标识。同时它会显式检查目标与当前请求的 hostname 与 path 是否一致,若一致则抛出InfiniteRedirectException,避免系统级无限重定向。

用户自定义重定向的四种类型

用户自定义重定向通过项目仪表盘(Admin > Redirects)配置,共有四种类型,对应源码 readthedocs/redirects/constants.py 中的TYPE_CHOICES。

Page Redirect(页面重定向)

Page Redirect允许你跨文档的所有版本重定向某个页面。由于它作用于项目的全部版本,From URL无需包含/<language>/<version>前缀(例如/en/latest),只需要页面的路径即可。

需要注意:页面重定向不适用于翻译(translations)和子项目(subprojects),这些项目需要各自配置自己的重定向规则。如果你需要针对特定语言或版本的 URL 进行重定向,请使用下面的 Exact Redirect,并填写完整路径。

Exact Redirect(精确重定向)

Exact Redirect会考虑完整的 URL(包括语言和版本),从而允许你为文档的特定版本或语言创建重定向。

Clean URL / HTML URL 互转重定向

如果你决定改变文档的 URL 风格,可以使用Clean URL to HTML(file/转file.html)或HTML to clean URL(file.html转file/)重定向,自动把读者引导到新的 URL 风格。例如某页面原来位于/en/latest/install.html,现在位于/en/latest/install/(或反之),用户都会被重定向到新地址。该类型在每个项目中每种只能配置一条(由 readthedocs/redirects/validators.py 中的校验逻辑保证)。

在仪表盘中配置重定向

完整操作步骤见图文指南,核心流程如下:

  1. 进入项目仪表盘,打开 :menuselection:Admin > Redirects;
  2. 点击 :guilabel:Add Redirect,选择 :guilabel:Redirect Type;
  3. 填写 :guilabel:From URL与 :guilabel:To URL,表单会提供实时预览,方便你实验最终生成的规则;
  4. 点击 :guilabel:Save保存。保存后规则立即生效。

编辑与删除规则同样在 :menuselection:Admin > Redirects页面完成。重定向的顺序很重要:当多条规则匹配同一个 URL 时,列表中的第一条会被采用。你可以用上/下箭头调整顺序,新建的重定向会添加到列表最前面(拥有最高优先级)。

Redirect模型的完整字段定义见 readthedocs/redirects/models.py:除project、redirect_type、from_url、to_url外,还包括:

字段类型/默认值说明
forceBoolean, 默认False强制重定向:即使目标页面存在也应用跳转
http_status默认302HTTP 状态码,可选302 - Temporary Redirect(临时)或301 - Permanent Redirect(永久)
enabledBoolean, 默认True启用/禁用该规则
positionInteger, 默认0规则执行顺序,配合上下箭头调整
descriptionString, 默认""规则描述

限制与注意事项

原文档总结了以下关键限制,配置时务必留意:

  • 数量限制:Read the Docs Community 用户每个项目最多 100 条重定向;Read the Docs for Business 用户的数量限制取决于其套餐。达到上限时会收到校验错误提示,并建议用通配符合并部分规则(校验逻辑见 readthedocs/redirects/validators.py,数量上限通过订阅功能TYPE_REDIRECTS_LIMIT读取)。
  • 默认仅对不存在的页面生效:默认情况下重定向只作用于不存在的页面(404 场景);Forced Redirect(强制重定向)允许你对已存在的页面也执行跳转。部分套餐才提供"即使页面存在也应用"选项。
  • 不作用于 Pull Request 预览:重定向不会应用于拉取请求预览的域名,这类域名应视为临时性的,不应依赖其承载面向用户的正式内容。
  • 可跳转到站外:To URL中包含协议(如https://example.com)即可重定向到 Read the Docs 之外的 URL。
  • 仅支持后缀通配符:通配符*只能放在From URL末尾(后缀通配符),用于重定向匹配某个前缀的所有页面;前缀和中缀通配符不支持。
  • :splat占位符:若From URL使用了通配符,URL 中被通配符捕获的部分可通过:splat占位符引用到To URL中。
  • 尾斜杠兼容:无通配符的规则会同时匹配带或不带尾斜杠的路径,例如/install同时匹配/install与/install/。
  • 顺序优先:多条规则命中同一 URL 时,第一条生效;顺序可在项目仪表盘调整。
  • 无限重定向保护:若检测到无限重定向,将直接返回 404,且不再应用其他规则。

实战示例大全

以下九个示例完整继承自原文档,覆盖从单页移动到整站迁移的全部常见场景。

1. 重定向单个页面

将example.html移动到子目录examples/intro.html:

Type: Page Redirect From URL: /example.html To URL: /examples/intro.html

效果:

  • https://docs.example.com/en/latest/example.html→https://docs.example.com/en/latest/examples/intro.html
  • https://docs.example.com/en/stable/example.html→https://docs.example.com/en/stable/examples/intro.html

如果只想对特定版本生效,改用精确重定向(注意使用目标版本和语言替换latest与en):

Type: Exact Redirect From URL: /en/latest/example.html To URL: /en/latest/examples/intro.html

2. 重定向整个目录

把/api/目录重命名为/api/v1/,无需为每个页面单独建规则,用通配符即可:

Type: Page Redirect From URL: /api/* To URL: /api/v1/:splat

效果:

  • https://docs.example.com/en/latest/api/→https://docs.example.com/en/latest/api/v1/
  • https://docs.example.com/en/latest/api/projects.html→https://docs.example.com/en/latest/api/v1/projects.html

限定版本时的精确重定向写法:

Type: Exact Redirect From URL: /en/latest/api/* To URL: /en/latest/api/v1/:splat

3. 目录重定向到单个页面

把/examples/目录的内容合并到examples.html单页:

Type: Page Redirect From URL: /examples/* To URL: /examples.html

效果:

  • https://docs.example.com/en/latest/examples/→https://docs.example.com/en/latest/examples.html
  • https://docs.example.com/en/latest/examples/intro.html→https://docs.example.com/en/latest/examples.html

4. 页面跳转到最新版本

让用户访问某个页面时总是跳到最新版本(例如安全策略页/security.html),结合通配符与强制重定向:

Type: Page Redirect From URL: /security.html To URL: https://docs.example.com/en/latest/security.html Force Redirect: True

效果:

  • https://docs.example.com/en/v1.0/security.html→https://docs.example.com/en/latest/security.html
  • https://docs.example.com/en/v2.5/security.html→https://docs.example.com/en/latest/security.html

注意:此处To URL必须包含完整域名,否则跳转会相对于当前版本解析,结果变成https://docs.example.com/en/v1.0/en/latest/security.html。

5. 旧版本跳转到新版本

/en/2.0/版本已废弃,希望读者跳转到/en/3.0/:

Type: Exact Redirect From URL: /en/2.0/* To URL: /en/3.0/:splat

效果:

  • https://docs.example.com/en/2.0/dev/install.html→https://docs.example.com/en/3.0/dev/install.html

注意:要让此规则生效,旧版本必须被禁用;如果版本仍处于激活状态,请使用Force Redirect选项。

6. 创建短链接

让https://docs.example.com/security跳转到https://docs.example.com/en/latest/security.html,便于分享:

Type: Exact Redirect From URL: /security To URL: /en/latest/security.html

效果(带与不带尾斜杠均可匹配):

  • https://docs.example.com/security(无尾斜杠)→https://docs.example.com/en/latest/security.html
  • https://docs.example.com/security/(带尾斜杠)→https://docs.example.com/en/latest/security.html

7. 迁移文档到 Read the Docs

原来文档托管在https://docs.example.com/dev/,迁移到 Read the Docs 后位于https://docs.example.com/en/latest/,但用户书签仍保存着旧结构(如https://docs.example.com/dev/install.html)。用带通配符的精确重定向:

Type: Exact Redirect From URL: /dev/* To URL: /en/latest/:splat

效果:

  • https://docs.example.com/dev/install.html→https://docs.example.com/en/latest/install.html

8. 迁移文档到另一个域名

用带强制选项的精确重定向把整个站点迁往新域名:

Type: Exact Redirect From URL: /* To URL: https://newdocs.example.com/:splat Force Redirect: True

效果:

  • https://docs.example.com/en/latest/install.html→https://newdocs.example.com/en/latest/install.html

9. 更换 Sphinx builder(html→dirhtml)

将 Sphinx builder 从html改为dirhtml后,所有 URL 都会从/page.html变成/page/。创建一条HTML to clean URL类型的重定向即可把所有旧 URL 引导到新风格(反向迁移则使用Clean URL to HTML)。

源码级实现原理

数据模型与 URL 规范化

Redirect模型(readthedocs/redirects/models.py)在save()时做了两件关键事情:

  1. 规范化from_url与to_url:normalize_from_url保证路径总是以单个/开头、不以/结尾,从而能同时匹配带与不带尾斜杠的路径;normalize_to_url则对非http(s)://开头的目标路径补上/前缀(models.py 的normalize_*方法)。
  2. 剥离通配符存储:若from_url以*结尾,会把去掉*的部分存入from_url_without_rest字段并建立数据库索引,以便在数据库层做快速前缀匹配(models.py#L134-L150)。

数据库层匹配查询

匹配逻辑集中在RedirectQuerySet.get_matching_redirect_with_path(readthedocs/redirects/querysets.py#L50-L145)。它通过annotate把当前请求的 filename/path 注入查询集,在数据库层完成过滤:

  • Page Redirect:无通配符时精确匹配文件名;有通配符时按from_url_without_rest做前缀匹配;
  • Exact Redirect:无通配符时精确匹配完整路径;有通配符时前缀匹配;
  • Clean/HTML 互转:当 filename 以/index.html或/结尾时匹配clean_url_to_html,以.html结尾时匹配html_to_clean_url;根路径(/index.html或/)只匹配 page 与 exact 规则;
  • 默认排除enabled=False的规则,并在forced_only模式下只筛选force=True的规则,然后按position、-update_dt排序取第一条。

无限重定向检测

无限重定向的典型形态是从 /dir/* 跳到 /dir/subdir/:splat:若目标文件不存在,/dir/test.html会依次跳到/dir/subdir/test.html、/dir/subdir/subdir/test.html……永无止境。_will_cause_infinite_redirect(models.py#L271-L293)通过检查"跳转目标是否为当前路径的子目录前缀"来识别此类循环:若to_url在:splat之前的部分以from_url_without_rest开头,且当前路径已以该目标前缀开头,则判定为无限重定向并返回None(此时平台返回 404 且不应用其他规则)。

校验规则

readthedocs/redirects/validators.py 中的validate_redirect统一服务于 Django 表单与 DRF 序列化器:

  • 旧版$rest通配符已移除,需改用*;
  • *必须位于路径末尾(否则报"通配符必须位于路径末尾"错误);
  • 只有from_url以*结尾时,to_url才能使用:splat占位符;
  • Clean/HTML 互转类型每项目每种仅允许一条;
  • 新建规则时检查订阅功能规定的数量上限。

响应生成与开放重定向防护

readthedocs/proxito/views/mixins.py 中的get_redirect_response负责生成最终跳转响应:

  • 调用project.redirects.get_matching_redirect_with_path(...)得到命中规则与目标路径;
  • 若To URL显式指向外部域名,则直接使用该 URL(但会对携带ticket等敏感参数的外部跳转记录警告日志);
  • 安全要点:若规则未显式指向外部域名,最终跳转会被强制约束在当前请求的同一域名内(current_url_parsed._replace(path=...)),以防开放重定向(open redirect)漏洞;
  • 原始请求与跳转目标的 query 参数会被合并后一同拼入最终 URL;
  • 跳转响应同时写入X-RTD-Redirect响应头与缓存标签。

此外,readthedocs/proxito/redirects.py 中的canonical_redirect处理三类规范域跳转:HTTP → HTTPS、跳转到项目的规范自定义域名、子项目域名跳转到主项目域名(含 Pull Request 预览版本),并同样执行 from/to URL 相同的无限跳转检查。

测试验证

仓库测试对上述行为有充分覆盖,可作进一步参考:

  • readthedocs/proxito/tests/test_old_redirects.py:验证/page/*重定向、带 query 参数的页面重定向、无限重定向规避(test_page_redirect_avoid_infinite_redirect)、通配符重定向(test_page_redirect_with_wildcard)、重定向不适用于翻译与子项目(test_page_redirect_does_not_apply_to_translations_or_subprojects)、带/不带尾斜杠匹配(test_page_redirect_with_and_without_trailing_slash)以及跨域重定向(test_page_redirect_crossdomain);
  • readthedocs/proxito/tests/test_full.py:验证/page/foo.html跳转到https://{host}/en/latest/foo.html;
  • readthedocs/redirects/tests/test_views.py:覆盖重定向视图层行为。

总结

重定向是文档项目长期健康运营的基础设施:内置重定向让外部链接永远指向最新内容,用户自定义重定向则让内容重构(改名、移动、合并、换版本、换域名、换 URL 风格)不再以 404 为代价。配置时牢记四条核心原则即可:默认只对 404 页面生效(需要时开启 Force)、通配符只能放在末尾、用:splat捕获片段、规则顺序决定命中优先级、跨域跳转必须带协议。在此基础上,结合readthedocs/redirects与readthedocs/proxito的源码实现,你可以准确预判每条规则在真实请求中的行为,并借助图文指南在仪表盘中快速落地。

  • 后端
  • 文档

【免费下载链接】readthedocs.org

The source code that powers readthedocs.org

项目地址:https://gitcode.com/gh_mirrors/re/readthedocs.org
点击查看免费下载

相关推荐

上一篇:如何安全运行AI Agent:awesome-harness-engineering沙箱隔离与提示注入防御终极清单
下一篇:智能IP段合并工具:高效管理网络地址的自动化解决方案

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询