Files
OpenFlare/docs/design/origin-error-page.md
T
ryan 600a7acdfb docs: 核查并润色文档,对齐项目实际实现
- 删除未经验证的环境要求(Docker 版本号、浏览器条目)与括号废话
- 故障排查改为真实处理路径(升级→重新发布→强制同步→重建 Agent→提交 issue),删除仅开发时用的排障章节
- 删除设计文档中的测试与验收、实现检查清单、贡献者阅读建议等开发内容
- 修正与代码不符的事实:reset-passwd 命令名、证书续签窗口 7 天、Pages 检查间隔 1440 分钟、Relay vhost 端口 8080、SSO 仅支持 OIDC 等
- 去除口语化表述与无意义括号,改写「不是…而是…」句式
- 同步修正文档站链接锚点,构建验证通过
2026-08-16 17:49:57 +08:00

8.1 KiB
Raw Blame History

源站错误页设计

你会学到:源站或网关返回指定错误状态码时,OpenFlare 如何用全局可配置页面替代透传响应;配置如何进入不可变配置版本,以及边缘 OpenResty 如何保持真实 HTTP 状态码并在页面中展示该状态码。

本设计是 系统架构 中反代流量路径的产品化补充;配置发布模型见 Agent 与发布模型。


1. 目标与非目标

1.1 目标

  • 可拦截:在用户配置的状态码集合上,用统一 HTML 替换原先透传的源站/Nginx 默认错误响应。
  • 可关闭:全局开关关闭后行为与现状一致(透传 / Nginx 默认页)。
  • 默认可视:默认启用,默认状态码标签 500-599,默认 OpenFlare 极简错误页。
  • 可自定义:管理员可在线编辑完整 HTML;空 HTML 表示使用内置默认模板。
  • 状态码透传:HTTP 响应 status 保持原错误码(如 502、522);页面正文通过 {{status}} 展示同一数值。
  • 全局统一:侧栏「网站管理 → 响应页面」单一配置,全站反代路由共用。
  • 与发布一致:配置经 Option 持久化,进入配置版本快照后随发布/回滚下发。

1.2 非目标

  • 按反代路由 / Zone 覆盖错误页
  • 通过上传文件托管错误页(仅在线 HTML)
  • 修改 WAF / PoW / 限流自有响应页(除非用户把对应状态码加入列表)
  • Pages 静态路由错误页
  • 多语言错误页、品牌资源 CDN

2. 产品行为

2.1 何时替换

条件 行为
开关开启,且响应状态码落在展开后的集合内 返回自定义/默认 HTML,status 不变
开关开启且启用 GET-only,非 GET 请求返回匹配状态码 透传源站原始响应,不替换
开关关闭 不生成 error_page 相关指令,透传
状态码不在集合内 不替换
Pages 上游路由 不应用本功能
源站成功返回 2xx/3xx/4xx(未配置时) 不替换

全方法模式下对反代 location 启用 proxy_intercept_errors on,因此源站返回的匹配 5xx 等也会被拦截,而不仅是网关本地生成的 502;GET-only 模式改用 Lua header/body 过滤器仅替换 GET 响应正文。

2.2 状态码标签语法

Tags Input 每条标签:

形式 示例 含义
单码 522 仅该码
闭区间 500-599 含端点展开
  • 合法范围:单码与区间两端均在 400–599;lo ≤ hi。
  • 默认标签列表:["500-599"]。
  • 持久化存原始标签(JSON 数组字符串);渲染时展开、去重、排序。
  • 启用时展开结果为空 → 保存拒绝。
  • 非法标签 → 保存拒绝并返回可读错误。

2.3 页面占位符

占位符 含义
{{status}} 当前响应状态码(与 HTTP status 一致)
{{host}} 请求 Host

自定义 HTML 与默认模板均支持上述占位符;运行时在边缘替换。未使用的占位符可不出现在模板中。

2.4 默认页

内置 OpenFlare 极简白底默认页:大号透传状态码、简短英文说明、Host 与品牌页脚。支持占位符 {{status}} / {{host}};前端可在编辑页从内置模板目录加载预制风格。


3. 配置模型

3.1 Option keys(w_system_configs / OpenFlare Option API)

Key 类型 默认 说明
origin_error_page_enabled bool 字符串 true 总开关
origin_error_page_status_codes JSON 字符串数组 ["500-599"] 原始标签
origin_error_page_html 文本 "" 空 = 内置默认;最大 256 KiB
origin_error_page_get_only bool 字符串 false 仅对 GET 请求替换错误页,其它方法透传

API 复用:

  • GET /api/v1/d/option
  • POST /api/v1/d/option/update-batch

不新增独立资源路由。goose 迁移写入 seed;常量定义于 internal/model 配置 key 区。

3.2 校验(update-batch)

  1. enabled:可解析为 bool。
  2. status_codes:合法 JSON 数组;每项 ^\d{3}$ 或 ^\d{3}-\d{3}$;展开后均在 400–599;启用时非空。
  3. html:长度 ≤ 256 KiB(按字节);允许空。
  4. 解析/展开逻辑为纯函数,供 API 与 pkg/render/openresty 共用,避免前后端/渲染语义分叉。

不对 HTML 做 XSS 消毒:属管理员全局运维配置,与边缘公开展示一致;文档提示勿嵌入不可信第三方脚本。

3.3 配置版本快照

ConfigSnapshot 增加字段:

OriginErrorPageEnabled     bool
OriginErrorPageStatusCodes []string  // 原始标签
OriginErrorPageHTML        string    // 空则渲染器用内置默认
OriginErrorPageGetOnly     bool

构建快照时从 Option 读取;Agent 只消费快照,不直读控制面 DB。


4. 边缘渲染

4.1 启用时生成内容

  1. SupportFile:错误页模板(如 error_pages/origin_error.html.tmpl),内容为自定义 HTML 或内置默认,保留 {{status}} / {{host}}。
  2. 每个反代 proxy server(含 HTTP/HTTPS 反代;不含 Pages):
proxy_intercept_errors on;
error_page <expanded codes...> @__openflare_origin_error;

location @__openflare_origin_error {
    default_type text/html;
    charset utf-8;
    content_by_lua_block {
        # 读取模板,替换 {{status}} / {{host}} 后输出 body
        # ngx.status 保持原错误码
    }
}

4.2 运行时替换

采用 命名 location 内 content_by_lua_block 读模板并替换占位符,不把 status 固化进静态文件(请求间状态码不同)。GET-only 模式在反代 location 内用 header_filter_by_lua_block + body_filter_by_lua_block 仅替换 GET 响应正文,非 GET 请求透传。

禁止将错误页统一改为 HTTP 200。

4.3 关闭时

不输出 proxy_intercept_errors、error_page、内部 location 与对应 SupportFile(或文件可写但不被引用)。GET-only 模式同时不输出 Lua 过滤器。

4.4 与缓存 / stale

若全局 proxy_cache_use_stale 在部分错误码上返回过期缓存,成功返回 stale 内容时不会进入 error_page。仅当实际上对客户端产生配置列表内错误状态时才展示错误页。行为依赖现有缓存指令,本功能不改 stale 策略。


5. 前端

5.1 入口

  • 侧栏「网站管理 → 响应页面」:错误页 Tab(/responses),编辑页 /responses/error-page/edit、预览页 /responses/error-page/preview。

5.2 页面结构

  • 页头说明:保存后需到「版本发布」发布才生效。
  • 开关 + Tags Input(shadcn-extension Tags Input:@/components/ui/tags-input):状态码标签。
  • HTML 编辑区 +「加载默认模板」「恢复默认(清空)」+ 占位符说明。
  • 客户端预览:用示例 status=502、host=example.com 替换后 sandbox/iframe 预览。
  • 保存:OptionService.updateBatch;权限与性能调优页一致(管理员)。

5.3 组件依赖

Tags Input 与 HTML 编辑器复用现有 shadcn/ui 组件,样式与现有 UI 一致。


6. 数据流

管理员 /responses(错误页 Tab)
    → Option update-batch(校验标签与 HTML)
    → w_system_configs

发布配置版本
    → 快照写入 OriginErrorPage*
    → 渲染 OpenResty conf + SupportFile
    → Agent 拉取并 reload

访客请求反代域名
    → 源站/网关产生匹配状态码
    → error_page → 命名 location
    → 替换占位符,status 保持原码,返回 HTML

7. 决策记录

决策 选择 原因
配置范围 全局 产品要求;实现与运维简单
存储 Option + 配置版本 与性能调优一致,可回滚
状态码输入 标签:单码与区间 默认整段 5xx,又可点名 522
响应 status 保持原码 监控/SEO/客户端语义正确
运行时替换 internal + 轻量模板替换 每请求 status 不同
自定义方式 在线 HTML 灵活且无需文件上传链路