现象
订阅页上有两个“查看状态页”入口,链接指向 /subscribe/status。但状态页的实现是:
const state = isSubscriptionState(urlState) ? urlState : 'invalid';
不带 ?state= 的直接访问全部落入 invalid 分支,标题赫然是**“链接无效 / 无法处理”**。也就是说,站点主动引导用户去点一个必然报错的页面。更糟的是这个无参数路径被收录进了 sitemap——搜索引擎抓回来的每一页都是错误提示。
根因
把“操作结果页”当成了“状态查询页”来设计。这个页面真实的语义只有一个:渲染某次订阅操作的结果,结果信息全部来自重定向携带的查询参数。它没有“查询当前订阅状态”的能力(那需要后端凭 token 或邮箱,属于另一个功能的范畴),但入口文案“查看状态页”承诺的恰恰是后者。语义与承诺错位,实现忠实于语义,于是入口一碰就碎。
修复
- 新增 idle 引导态:
state参数缺失时不再判死,渲染使用说明——告诉访客这个页面会在校验邮箱、确认、退订后自动到达,并提供“前往订阅 / RSS / 返回首页”三个出口。invalid回归本义:参数存在但无法识别。 - sitemap 移除该路由:带参数才有意义、且每次访问内容都不同的结果页,不是可索引文档。
- 顺带清理了同类问题:一个挂在公开路由的管理预览页(含受保护 API 链接,访客点击得到裸 401 JSON)整体迁入后台并加会话守卫。
教训
- 每一个能导航到达的 URL,都要回答“用户不带任何上下文直接访问时,看到什么”。 答案不应该是错误页——除非它真的是 404。
- 结果页 / 回跳页默认不进 sitemap;能进 sitemap 的页面必须是无参数可稳定渲染的。
- 状态映射建议至少留三态:缺参(idle 引导)、坏参(invalid 纠错)、好参(正常渲染)。二元判断是这类事故的温床。