From 6738abdec1ca1ff79cc2f65838b1b8c0602bf8ed Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 6 Aug 2026 20:22:44 +0800 Subject: [PATCH] feat(openresty): add origin error page GET-only option Allow restricting custom origin error HTML to GET requests so other methods pass through origin responses. Adds option seed, snapshot field, edge limit_except/Lua handling, and admin UI switch. --- docs/changelog/index.md | 1 + docs/reference/configuration.md | 1 + .../(main)/error-pages/components/shared.ts | 5 +++ frontend/app/(main)/error-pages/page.tsx | 27 +++++++++++++-- .../apps/openflare/config_version/logics.go | 2 ++ .../apps/openflare/config_version/snapshot.go | 2 ++ .../openflare/option/openresty_validators.go | 1 + ...8060002_add_origin_error_page_get_only.sql | 8 +++++ ...8060002_add_origin_error_page_get_only.sql | 8 +++++ internal/model/system_configs.go | 1 + pkg/render/openresty/origin_error_page.go | 33 +++++++++++++++--- .../openresty/origin_error_page_test.go | 34 +++++++++++++++++++ pkg/render/openresty/types.go | 2 ++ 13 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 internal/infra/persistence/migrator/goose/postgres/202608060002_add_origin_error_page_get_only.sql create mode 100644 internal/infra/persistence/migrator/goose/sqlite/202608060002_add_origin_error_page_get_only.sql diff --git a/docs/changelog/index.md b/docs/changelog/index.md index e32fe4d3..13e1dfa4 100644 --- a/docs/changelog/index.md +++ b/docs/changelog/index.md @@ -35,6 +35,7 @@ sidebar: false ### 新增 - 新增全局源站错误页:可在「网站管理 → 错误页」配置开关、触发状态码(支持 `500-599` 区间与单码)与自定义 HTML;默认启用 OpenFlare 极简错误页并保持真实 HTTP 状态码,修改后随配置版本发布下发到边缘,关闭后恢复透传。 +- 源站错误页支持「仅针对 GET 请求」:开启后仅对 GET 的匹配错误状态码返回自定义错误页,其它 HTTP 方法透传源站响应。 - 新增 Cloudflare DNS 指向管理:可复用现有 Cloudflare DNS 账号或配置独立 Token,按分组将 ZoneDomain 的单条 A 记录异步同步到边缘节点 IPv4,并支持成员橙云、同步状态与节点 IP 变更联动。 ### 修复 diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index a07e7d3b..b8652188 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -266,6 +266,7 @@ Server 的所有核心基础配置定义在 `config.yaml` 中,且均支持环 | 配置键 (Key) | 数据类型 | 作用说明 | 默认值 | | --- | --- | --- | --- | | `origin_error_page_enabled` | `bool` | 是否启用全局源站错误页。开启后,源站或网关返回的匹配状态码由自定义/默认 HTML 替换,**HTTP 状态码保持原值**;关闭后不生成相关指令,恢复透传。修改后需发布配置版本生效 | `true` | +| `origin_error_page_get_only` | `bool` | 是否仅对 **GET** 请求生效。开启后仅 GET 的匹配错误状态码返回自定义错误页;POST/PUT 等其它方法透传源站响应 | `false` | | `origin_error_page_status_codes` | `json` | 触发错误页的状态码标签 JSON 数组。支持单码(如 `522`)与闭区间(如 `500-599`);单码与区间两端均须在 **400–599**,且 `lo ≤ hi`。启用时展开结果不能为空 | `["500-599"]` | | `origin_error_page_html` | `string` | 错误页自定义 HTML。空字符串表示使用内置 OpenFlare 默认模板(极简白底);支持占位符 `{{status}}`(与 HTTP 状态码一致)、`{{host}}`(请求 Host)。最大 **256 KiB**(按字节)。勿嵌入不可信第三方脚本 | 空 | diff --git a/frontend/app/(main)/error-pages/components/shared.ts b/frontend/app/(main)/error-pages/components/shared.ts index ffa77870..511ca26d 100644 --- a/frontend/app/(main)/error-pages/components/shared.ts +++ b/frontend/app/(main)/error-pages/components/shared.ts @@ -10,15 +10,18 @@ export const OPTIONS_QUERY_KEY = ['openflare', 'options'] as const; export const KEY_ENABLED = 'origin_error_page_enabled'; export const KEY_STATUS_CODES = 'origin_error_page_status_codes'; export const KEY_HTML = 'origin_error_page_html'; +export const KEY_GET_ONLY = 'origin_error_page_get_only'; export type ErrorPageFields = { enabled: boolean; + getOnly: boolean; statusCodes: string[]; html: string; }; export const defaultErrorPageFields: ErrorPageFields = { enabled: true, + getOnly: false, statusCodes: [...DEFAULT_ORIGIN_ERROR_PAGE_STATUS_TAGS], html: '', }; @@ -34,8 +37,10 @@ export function mapOptionsToFields( optionMap: Record, ): ErrorPageFields { const enabledRaw = optionMap[KEY_ENABLED]; + const getOnlyRaw = optionMap[KEY_GET_ONLY]; return { enabled: enabledRaw === undefined ? true : enabledRaw === 'true', + getOnly: getOnlyRaw === undefined ? false : getOnlyRaw === 'true', statusCodes: parseStatusCodeTagsJSON(optionMap[KEY_STATUS_CODES]), html: optionMap[KEY_HTML] ?? '', }; diff --git a/frontend/app/(main)/error-pages/page.tsx b/frontend/app/(main)/error-pages/page.tsx index 76b906bc..02c7aaa6 100644 --- a/frontend/app/(main)/error-pages/page.tsx +++ b/frontend/app/(main)/error-pages/page.tsx @@ -30,6 +30,7 @@ import { defaultErrorPageFields, invalidateErrorPageQueries, KEY_ENABLED, + KEY_GET_ONLY, KEY_STATUS_CODES, mapOptionsToFields, OPTIONS_QUERY_KEY, @@ -60,12 +61,13 @@ export default function ErrorPagesPage() { [fields.html], ); - /** 仅保存启用开关 + 触发状态码(HTML 在编辑页单独保存) */ + /** 仅保存策略项(HTML 在编辑页单独保存) */ const savePolicyMutation = useMutation({ mutationFn: async () => { validateStatusCodeTags(fields.statusCodes); await OptionService.updateBatch([ { key: KEY_ENABLED, value: String(fields.enabled) }, + { key: KEY_GET_ONLY, value: String(fields.getOnly) }, { key: KEY_STATUS_CODES, value: JSON.stringify(fields.statusCodes), @@ -124,13 +126,34 @@ export default function ErrorPagesPage() { + + +
+ 仅针对 GET 请求 + + 开启后仅对 GET + 请求的匹配错误状态码返回自定义错误页;POST/PUT + 等其它方法直接透传源站响应。 + +
+ + setFields((prev) => ({ ...prev, getOnly })) + } + aria-label='仅针对 GET 请求' + /> +
+
+
触发状态码 支持单码(如 502)或闭区间(如 500-599),范围 400–599。默认 - 500-599。修改启用开关或状态码后需点击保存。 + 500-599。修改策略开关或状态码后需点击保存。