新闻详情

新闻详情

首页 / 资讯中心 / 详情

Read the Docs 重定向系统设计:从五种重定向类型到 `*` / `:splat` 新语法与源码实现

发布时间:2026/9/25 5:18:19来源:尧图网络
Read the Docs 重定向系统设计:从五种重定向类型到 `*` / `:splat` 新语法与源码实现
后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载本文基于 Read the Docs下称 RTD的设计文档 redirects.rst 展开系统讲解 RTD 重定向功能的目标与非目标、五类重定向的语义差异、对标 Gitbook / Cloudflare / Netlify 等平台的取舍以及*通配符与:splat占位符、路径归一化、显式排序等改进方案在仓库中的实际落地读完后你将理解 RTD 重定向从用户创建到请求匹配、跳转生成的完整链路并能对照源码验证每一项设计决策的实现细节。背景与目标重定向是 RTD 的核心功能之一当用户重命名或移动文档页面时重定向可以让旧 URL 继续可用避免破坏外部引用。设计文档开篇即指出当时的实现“缺少一些功能并且存在未定义/未文档化的行为”因此需要一次系统性的改进。文档给出的目标Goals非常聚焦改进创建重定向时的用户体验在不引入大面积破坏性变更big breaking changes的前提下改进现有实现。非目标Non-goals同样明确体现了“不做没有清晰用例的功能”的克制不为了对齐其他服务而复制其全部功能不以提高重定向性能为目标性能在实现新改进时会被考虑但单独的性能优化放到 issue/PR 中讨论;不提供重定向导入能力而是引导用户使用 API不允许在 RTD 配置文件中声明重定向——团队有过多次讨论但未达成共识。现状五类重定向设计文档梳理了当时存在的五种重定向类型这是理解后续合并、改名等改造的基线前缀重定向Prefix redirect把以某个前缀开头的所有 URL 重定向到新 URL使用项目的默认版本和语言。例如值为/prefix/的前缀重定向会把/prefix/foo/bar重定向到/en/latest/foo/bar。本质上它等价于一条“末尾带通配符的精确重定向”可以看作一条简写From:/prefix/$restTo:/en/latest/页面重定向Page redirect把单个页面重定向到新 URL使用当前的版本和语言。例如值为/old/page.html的页面重定向会把/en/latest/old/page.html重定向到/en/latest/new/page.html。文档特别强调了三条限制页面重定向不允许跨域cross domain它对所有版本生效若只想对某个版本生效应使用精确重定向页面重定向不能重定向整个目录目录迁移需要用末尾带通配符的精确重定向在单版本项目中页面重定向与精确重定向等价。精确重定向Exact redirect把某个精确 URL 重定向到新 URL允许在末尾使用通配符。例如值为/en/latest/page.html的精确重定向会把该 URL 重定向到新地址。若值为/en/latest/dir/$rest则所有以/en/latest/dir/开头的路径都会被重定向剩余路径会自动拼接到新 URL 上。要点包括允许跨域、对所有版本生效、通配符只能放在 URL 末尾、使用通配符时剩余路径自动拼接到目标 URL。两类 Sphinx 重定向Sphinx HTMLDir to HTML把 clean-URL 重定向到 HTML URL例如file/到file.html适合项目更换 URL 风格时使用Sphinx HTML to HTMLDir把 HTML URL 重定向到 clean-URLfile.html到file/。两者都适用于所有类型的项目而不仅限于 Sphinx 项目——这一点是后来改名决策的直接依据。业界实现参考文档对比了同类平台的通配与占位符能力为 RTD 的新语法选择提供了参照系仅陈述能力差异不涉及外部链接平台占位符通配符其他能力Gitbook无无仅支持页面重定向实现非常基础Cloudflare Pages支持支持一个通配符URL 任意位置可设置状态码_redirects文件声明上限 2100 条多条匹配时取最上面一条Netlify支持仅允许在末尾可设置状态码强制重定向匹配 query 参数按国家/语言/Cookie 匹配按域/协议区分rewrite不换 URL 直接换内容多条匹配取最上面一条GitLab Pages支持支持splat与 Netlify 同语法支持其子集_redirects文件、状态码、rewrite、通配符、占位符这些对比直接催生了后文*/:splat的命名与“显式占位符”方案。改进方案与源码落地通用改进状态码、排序、启用/禁用、描述文档提出对所有类型生效的四项通用改进且四项在当前仓库中均已落地全部体现在 Redirect 模型 上允许选择状态码文档指出“我们本来就有这个字段只是没暴露给用户”。模型中http_status默认 302可选值为 301 / 302定义于 HTTP_STATUS_CHOICEShttp_status models.SmallIntegerField( _(HTTP status code), choicesHTTP_STATUS_CHOICES, default302, )显式定义重定向顺序文档说明此前依赖updated_at的隐式顺序改进方式类似自动化规则automation rules——用户可把更具体的规则排到前面。模型新增了position字段并把默认排序改为先按position再按-update_dtmodels.py#L111-L130并复用了ProjectItemPositionManager在保存/删除时维护顺序与 automation rules 共用同一套位置管理机制。允许禁用重定向便于测试或排障时临时关闭再重新启用无需删除重建。对应enabled字段默认True查询匹配时通过.exclude(enabledFalse)过滤querysets.py#L131-L134。允许添加简短描述用于记录“为什么创建这条重定向”对应description字段255 字符。不在 Pull Request 预览域名上执行重定向文档指出现行实现会在 PR 预览域名上执行重定向这在“把整个项目迁移到新域名”时会造成干扰PR 预览域名属于临时域名不应执行重定向。这一条目属于请求侧的行为约束与下文请求链路proxito 层配合实现。末尾斜杠归一化此前用户若要同时覆盖/page/与/page必须创建两条重定向。改进方案是在匹配前或保存前归一化路径使一条/page/ - /new/page的重定向同时匹配带与不带斜杠的访问。文档同时指出代价归一化后将无法再匹配带末尾斜杠的路径。并且只有 page/exact 两类“末尾无通配符”的重定向做归一化其余类型必须按原样匹配。源码中这一设计在两个层面实现保存侧Redirect.save()对非 clean/HTML 类型调用normalize_from_url()——去掉末尾斜杠、保证以单个/开头models.py#L134-L166to_url则只补前导/且绝对 URLhttp(s)://开头保持原样def normalize_from_url(self, path): path path.rstrip(/) path / path.lstrip(/) return path匹配侧get_matching_redirect_with_path()用_normalize_path()去掉 query 参数并保证前导/再用_strip_trailling_slash()生成“去尾斜杠”版本参与精确匹配querysets.py#L50-L145。注释里明确写着目的“/docs同时匹配/docs/和/docs”。用*与:splat替换$rest现行语法用$rest表示“把剩余路径拼到目标 URL”与其他平台常用的*:splat不一致。新方案源 URL 末尾使用*表示后缀通配符目标 URL 中使用:splat作为占位符存量重定向可自动迁移。常量层面SPLAT_PLACEHOLDER :splat定义于 constants.py#L14。为提升查询性能模型额外保存了一个去通配符副本from_url_without_rest专门用于数据库层的startswith匹配models.py#L66-L73if self.from_url.endswith(*): self.from_url_without_rest self.from_url.removesuffix(*)校验层则对新旧语法做了硬性约束validate_redirect使用$rest会直接报错The $rest wildcard has been removed in favor of *.——即旧语法被正式废弃*必须位于from_url末尾若to_url含:splat则from_url必须以*结尾。显式:splat占位符旧行为是“自动把剩余路径拼到目标 URL”副作用是当用户只想跳到固定路径时只能靠?_之类的查询参数“污染”目标 URL 来阻止自动拼接。新方案改为由用户显式声明只有目标 URL 中写了:splat剩余路径才会被拼接从而支持把剩余路径放进任意位置包括查询参数From: /old/path/* To: /new/path/:splat From: /old/path/* To: /new/path/?page:splatfoobar核心拼接逻辑在_redirect_with_wildcard()splat current_path[len(self.from_url_without_rest):] to_url self.to_url.replace(SPLAT_PLACEHOLDER, splat)值得注意的是文档中没有讨论但源码中实现了无限重定向环检测_will_cause_infinite_redirect()专门识别/dir/* - /dir/subdir/:splat这种模式——若目标路径是源路径的子目录且当前请求路径已经以目标前缀开头则返回None放弃重定向避免/dir/test.html被反复改写为/dir/subdir/subdir/...。这是显式:splat语义引入的一类新风险源码用保守策略兜底。页面重定向的改进文档提出两项增强源码均可印证允许重定向到外部域名。文档给出的动机是对知名路径如/security/在所有版本统一跳转到其他域名的安全政策页且能简化功能解释少一条限制。实现上redirect_page()调用get_full_path(..., allow_crossdomainTrue)而get_full_path()在允许跨域时直接返回https?://开头的目标地址models.py#L216-L232。请求侧则做了安全加固get_redirect_response() 在重定向未显式指向外部域名时强制把最终 URL 钉在当前请求的域名上注释明确写着“避免 open redirect 漏洞”若目标确实跨域且请求带ticket参数则记录告警日志。from路径允许末尾通配符使用户可以“把一个整目录迁移到新路径而不用为每个版本建精确重定向”。由此页面重定向与精确重定向的唯一区别只剩“是否对所有版本生效”与文档预期一致。匹配逻辑上带通配符的页面重定向走filename__startswithF(from_url_without_rest)分支querysets.py#L94-L111。前缀重定向合并进精确重定向文档论证前缀重定向本就等价于“末尾带通配符的精确重定向”因此将全部前缀重定向迁移为通配符精确重定向。迁移映射示例原: From: /prefix/ 新: From: /prefix/* To: /en/latest/:splat其中/en/latest是项目的默认版本和语言单版本项目则迁移为From: /prefix/*→To: /:splat。在当前代码中TYPE_CHOICES 已经只剩四类page、exact、clean_url_to_html、html_to_clean_url前缀类型不复存在印证了合并完成。重命名 Sphinx 重定向因为两类 Sphinx 重定向实际适用于所有构建工具的项目文档提议改名为更通用的表述最终命名可见于 constants.py#L16-L21Clean URL to HTML (file/ to file.html)常量CLEAN_URL_TO_HTML_REDIRECTHTML to clean URL (file.html to file/)常量HTML_TO_CLEAN_URL_REDIRECT。数据迁移由 0007_migrate_to_new_syntax.py 完成把sphinx_html批量改写为clean_url_to_html、sphinx_htmldir改写为html_to_clean_url把enabledNone的存量记录置为True并按-update_dt顺序为每条重定向写入position——即把旧版“隐式的 updated_at 顺序”固化成显式的position值恰好完成了上文“显式排序”的数据迁移。迁移文件还特别说明通配符语法的迁移放在 migration 之外执行因为历史模型缺少迁移所需的方法。两类 URL 风格重定向的转换逻辑也很直白models.py#L311-L336redirect_clean_url_to_html仅当文件名以/或/index.html结尾时生效把前缀改写为.html空前缀落到index.htmlredirect_html_to_clean_url把.html后缀替换为/。匹配侧按文件名后缀“路由”到不同类型/index.html或/只匹配 page/exact以/index.html或/结尾追加clean_url_to_html以.html结尾追加html_to_clean_urlquerysets.py#L115-L129。此外 validate_redirect() 限制每项目每类最多一条。其他候选改进首期不实现文档还列出了一批“不会在第一迭代实现”的想法以及各自的判断依据对理解后续演进很有价值强制重定向先于内置重定向执行当前内置built-in重定向先跑导致整站迁移时/$rest这类强制规则对根 URL 失效/会先被重定向到/en/latest/但影响有限用户仍要处理/en/latest/file/路径。内置/规范重定向的现有实现在 proxito/redirects.py 中覆盖 http→https、规范域名、子项目到主域等场景在边缘执行重定向Cloudflare 支持边缘重定向但规则数量有限制且只能用于“强制精确重定向”——边缘无法基于源站响应来判定是否重定向合并为单一重定向类型实现会更简单但用户理解成本更高且合并前提是先补齐若干新能力占位符目前没有用户请求未来可考虑暴露当前语言/版本作为占位符按协议区分官方立场是引导用户始终使用 HTTPS前缀通配符目前仅支持后缀通配符加前缀通配符实现不难但缺乏用户诉求按域区分原始诉求源于“重定向被应用到了外部域名”若停止该行为此需求即消失可转而改进内置重定向尤其规范域名重定向。Query 参数匹配三种候选方案“允许按 query 参数匹配”只有单一用户提出优先级低但文档给出了完整的方案权衡数据库层 受限语义拆成“纯路径字段”与“归一化排序后的查询串字段”如/foo?blue1yellow2red3归一化为路径/foo与blue1red3yellow2。限制在于请求的查询参数必须完全一致不多不少。文档认为 Netlify 采用即此类方案因其有同样的限制数据库层 JSONField查询参数以归一化字典存储匹配时用has_keys与contained_by组合约束参数个数Python 层匹配路径仍在数据库层匹配查询参数在 Python 层灵活匹配可允许请求带额外参数。文档指出历史上的性能问题“主要来自使用正则而非字符串操作”并可用限制“带查询参数的重定向条数”或“总条数”来控制开销。迁移策略文档结论大部分改进向后兼容只需一次数据迁移归一化存量重定向唯一需要用户“重新学习”的是目标 URL 中显式:splat——旧用户可能仍期待路径被自动拼接因此计划发布一篇博客文章说明变化。仓库中 0007 迁移 与模型/校验层的变更共同构成了这一策略的落地。端到端请求链路与补充细节把上述碎片串起来一次请求的重定向链路是proxito 文档服务层调用get_redirect_response()内部委托project.redirects.get_matching_redirect_with_path(...)QuerySet 在数据库层用annotateQ组合完成类型过滤、尾斜杠归一化匹配、通配符startswith匹配、enabled过滤并按模型的(position, -update_dt)顺序取第一条“多条匹配取最靠前者”与 Cloudflare/Netlify 的语义一致命中后调用get_redirect_path()按redirect_{type}分派到具体方法*类型走_redirect_with_wildcard()做:splat替换并做无限环检测返回响应前合并原始请求与目标 URL 的查询参数保持keep_blank_values并做跨域安全处理重定向响应的 HTTP 状态取自redirect.http_status。两个文档未展开、但由代码补充的边界事实数量上限_check_redirects_limit() 按订阅计划TYPE_REDIRECTS_LIMIT限制每项目重定向条数超限提示“用通配符重定向替代”私有仓库部署还会提示升级计划——这与文档“限制总数”的讨论相呼应clean/HTML 两类重定向每项目各限一条见 validators.py#L36-L43。小结这篇设计文档的价值在于把“重定向”这一看似简单的功能拆成了清晰的可决策单元哪些类型该合并prefix → exact、哪些该改名Sphinx → clean/HTML URL、哪些语义该收紧显式:splat、尾斜杠归一化、哪些明确不做配置文件中声明、导入、性能专项。对照 readthedocs/redirects/ 的模型、查询集、校验器 与 0007 迁移 可以看到文档中的主要提案均已实现$rest被*/:splat取代且旧写法直接拒绝排序、启停、描述、状态码全部字段化匹配下推到数据库层并额外增加了无限重定向环检测与开放重定向防护。对于需要在自建文档平台中设计重定向能力的开发者这套“文档定语义、模型存状态、QuerySet 做匹配、迁移保兼容”的拆解方式本身就是一个可复用的工程模板。赞分享后端文档【免费下载链接】readthedocs.orgThe source code that powers readthedocs.org项目地址https://gitcode.com/gh_mirrors/re/readthedocs.org点击查看免费下载相关推荐Vue Router 2 指南Redirect 重定向与 Alias 别名 —— 从配置语法到源码实现Vue Router 2 指南Redirect 重定向与 Alias 别名 —— 从配置语法到源码实现 本文围绕 Vue RouterVue 2 官方路由前端路由Read the Docs 新版搜索 API 设计解析key:value 语法、多项目搜索与实现落地Read the Docs 新版搜索 API 设计解析key:value 语法、多项目搜索与实现落地 本篇技术文章基于 Read the Docsreadt后端文档Read the Docs Organizations 设计解析从双站统一到共享 App 的落地实现Read the Docs Organizations 设计解析从双站统一到共享 App 的落地实现 本文基于 Read the Docs下称 RTD官方后端文档上一篇深入理解 roc 的 Str.starts_with从 REPL 边界测试到 Zig 运行时实现下一篇runMacOSinVirtualBox技术揭秘EFI引导与APFS驱动自动修复机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Keil uVision2安装使用教程:51单片机C51开发环境搭建避坑指南 2026/9/25 6:29:50

Keil uVision2安装使用教程:51单片机C51开发环境搭建避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
芯片烧录固件版本管理:命名、哈希与工具链匹配避坑指南 2026/9/25 6:29:50

芯片烧录固件版本管理:命名、哈希与工具链匹配避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
移动机顶盒CM211-1刷机全攻略:短接、固件选择与救砖实战 2026/9/25 6:29:50

移动机顶盒CM211-1刷机全攻略:短接、固件选择与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
C语言斐波那契数列详解:递推、数组与递归的坑与取舍 2026/9/25 6:29:44

C语言斐波那契数列详解:递推、数组与递归的坑与取舍

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Aster:Windows原生Session级副屏实现一机双桌面 2026/9/25 6:29:44

Aster:Windows原生Session级副屏实现一机双桌面

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
iOS高版本备份降级恢复原理与实操指南 2026/9/25 6:29:44

iOS高版本备份降级恢复原理与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉