mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-28 05:46:36 +08:00
454542c1d0
- README 默认英文:README.en.md → README.md(英文为默认),中文移至 README.zh-CN.md,语言切换链接同步 - 恢复被删除的 docs/en/ 英文文档(git 历史 cc5e53c5^),删除 4 篇已废弃文件 - 英文导航 config.ts 对齐中文结构(新增 Deployment/Changelog 侧栏,同步 Guide/Design 条目) - 翻译 15 篇中文新增文档:guide 5 篇(certificates/pages-usage/proxy-config/uptime-kuma/zone-domain-migration)+ design 10 篇(zone-design/cloudflare-pointing/waf-orchestration/origin-error-page/edge-cache-design/pages-design/logstore/kuma-design/login-captcha/observability 三篇) - en 首页更新(新增 Pages 特性、tagline 同步);changelog 英文入口指向中文版 - vitepress 构建验证:43 个英文页面全部渲染 注意:29 篇旧英文文档为恢复版,部分内容(如 deployment/server、reference/configuration)可能落后于中文,需后续逐篇同步
205 lines
8.9 KiB
Markdown
205 lines
8.9 KiB
Markdown
# Origin Error Page Design
|
||
|
||
You will learn: when an origin or the gateway returns a specified error status code, how OpenFlare replaces the pass-through response with a globally configurable page; how the config enters the immutable config version; and how the edge OpenResty keeps the real HTTP status code while displaying it in the page.
|
||
|
||
This design is the productized complement of the reverse proxy traffic path in [System Architecture](./architecture.md); the config release model is in [Agent & Publish Model](./agent-design.md).
|
||
|
||
---
|
||
|
||
## 1. Goals and Non-Goals
|
||
|
||
### 1.1 Goals
|
||
|
||
* **Interceptable**: for a user-configured status code set, replace the previously pass-through origin/Nginx default error response with a unified HTML.
|
||
* **Disableable**: when the global switch is off, behavior matches today (pass-through / Nginx default page).
|
||
* **Visible by default**: enabled by default, default status code tag `500-599`, default minimal OpenFlare error page.
|
||
* **Customizable**: admins can edit the full HTML online; empty HTML means the built-in default template.
|
||
* **Status passthrough**: the HTTP response `status` keeps the original error code (e.g. 502, 522); the page body shows the same value via `{{status}}`.
|
||
* **Globally unified**: a single config under sidebar「Website Management → Response Pages」shared by all reverse proxy routes.
|
||
* **Consistent with release**: the config persists via Option, enters the config version snapshot, and is distributed with release/rollback.
|
||
|
||
### 1.2 Non-Goals
|
||
|
||
* Per-route / per-Zone error page overrides
|
||
* Hosting error pages via file upload (online HTML only)
|
||
* Modifying WAF / PoW / rate-limit's own response pages (unless the user adds those status codes to the list)
|
||
* Pages static route error pages
|
||
* Multi-language error pages, brand asset CDN
|
||
|
||
---
|
||
|
||
## 2. Product Behavior
|
||
|
||
### 2.1 When to Replace
|
||
|
||
| Condition | Behavior |
|
||
| --- | --- |
|
||
| Switch on and the response status falls in the expanded set | return custom/default HTML, **status unchanged** |
|
||
| Switch on with GET-only enabled, non-GET request returns a matching status | pass through the origin's raw response, no replacement |
|
||
| Switch off | no `error_page` directives generated, pass through |
|
||
| Status not in the set | no replacement |
|
||
| Pages upstream routes | this feature is not applied |
|
||
| Origin returns 2xx/3xx/4xx successfully (not configured) | no replacement |
|
||
|
||
In all-methods mode, `proxy_intercept_errors on` is enabled on the reverse proxy `location`, so **origin-returned** matching 5xx etc. are also intercepted, not just gateway-local 502s; GET-only mode switches to Lua header/body filters that only replace GET response bodies.
|
||
|
||
### 2.2 Status Code Tag Syntax
|
||
|
||
Each Tags Input entry:
|
||
|
||
| Form | Example | Meaning |
|
||
| --- | --- | --- |
|
||
| Single code | `522` | only that code |
|
||
| Closed range | `500-599` | expand including endpoints |
|
||
|
||
* Valid range: single codes and range endpoints must be in **400–599**; `lo ≤ hi`.
|
||
* Default tag list: `["500-599"]`.
|
||
* Persist the **raw tags** (JSON array string); expand, dedupe, and sort at render time.
|
||
* If the expanded result is empty while enabled → save rejected.
|
||
* Invalid tags → save rejected with a readable error.
|
||
|
||
### 2.3 Page Placeholders
|
||
|
||
| Placeholder | Meaning |
|
||
| --- | --- |
|
||
| `{{status}}` | the current response status code (consistent with the HTTP status) |
|
||
| `{{host}}` | request Host |
|
||
|
||
Both custom HTML and the default template support these placeholders; replaced at the edge at runtime. Unused placeholders may be omitted from the template.
|
||
|
||
### 2.4 Default Page
|
||
|
||
Built-in minimal white-background OpenFlare default page: large pass-through status code, short English description, Host, and a brand footer. Supports `{{status}}` / `{{host}}`; the frontend can load prebuilt styles from the built-in template catalog on the edit page.
|
||
|
||
---
|
||
|
||
## 3. Config Model
|
||
|
||
### 3.1 Option Keys (`w_system_configs` / OpenFlare Option API)
|
||
|
||
| Key | Type | Default | Description |
|
||
| --- | --- | --- | --- |
|
||
| `origin_error_page_enabled` | bool string | `true` | master switch |
|
||
| `origin_error_page_status_codes` | JSON string array | `["500-599"]` | raw tags |
|
||
| `origin_error_page_html` | text | `""` | empty = built-in default; max **256 KiB** |
|
||
| `origin_error_page_get_only` | bool string | `false` | replace error pages only for GET; other methods pass through |
|
||
|
||
Reuses APIs:
|
||
|
||
* `GET /api/v1/d/option`
|
||
* `POST /api/v1/d/option/update-batch`
|
||
|
||
No new resource routes. goose migration writes the seed; constants defined in the `internal/model` config key area.
|
||
|
||
### 3.2 Validation (update-batch)
|
||
|
||
1. `enabled`: parseable as bool.
|
||
2. `status_codes`: valid JSON array; each entry `^\d{3}$` or `^\d{3}-\d{3}$`; expanded values all in 400–599; non-empty when enabled.
|
||
3. `html`: length ≤ 256 KiB (bytes); empty allowed.
|
||
4. Parse/expand logic is a **pure function** shared by the API and `pkg/render/openresty` to avoid semantic forks.
|
||
|
||
No XSS sanitization on HTML: it's an admin global ops config consistent with public edge display; docs warn not to embed untrusted third-party scripts.
|
||
|
||
### 3.3 Config Version Snapshot
|
||
|
||
`ConfigSnapshot` adds fields:
|
||
|
||
```text
|
||
OriginErrorPageEnabled bool
|
||
OriginErrorPageStatusCodes []string // raw tags
|
||
OriginErrorPageHTML string // empty => renderer uses built-in default
|
||
OriginErrorPageGetOnly bool
|
||
```
|
||
|
||
Read from Option when building the snapshot; the Agent only consumes the snapshot, never reading the control-plane DB directly.
|
||
|
||
---
|
||
|
||
## 4. Edge Rendering
|
||
|
||
### 4.1 Content Generated When Enabled
|
||
|
||
1. **SupportFile**: error page template (e.g. `error_pages/origin_error.html.tmpl`), content is the custom HTML or built-in default, keeping `{{status}}` / `{{host}}`.
|
||
2. **Each reverse proxy server** (HTTP/HTTPS proxy; excluding Pages):
|
||
|
||
```nginx
|
||
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 {
|
||
# read template, replace {{status}} / {{host}}, output body
|
||
# ngx.status keeps the original error code
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 Runtime Replacement
|
||
|
||
Use a **named location with `content_by_lua_block`** to read the template and replace placeholders — the status is **not** baked into a static file (status differs per request). GET-only mode uses `header_filter_by_lua_block` + `body_filter_by_lua_block` inside the reverse proxy location to replace only GET response bodies; non-GET requests pass through.
|
||
|
||
Never rewrite the error page to HTTP 200.
|
||
|
||
### 4.3 When Disabled
|
||
|
||
Do not output `proxy_intercept_errors`, `error_page`, the internal location, or the corresponding SupportFile (or the file may be written but unreferenced). GET-only mode also omits the Lua filters.
|
||
|
||
### 4.4 Interaction with Cache / Stale
|
||
|
||
If global `proxy_cache_use_stale` returns stale cache for some error codes, **successful stale responses never enter `error_page`**. The error page is only shown when the client actually receives an error status in the configured list. Behavior depends on existing cache directives; this feature does not change stale policy.
|
||
|
||
---
|
||
|
||
## 5. Frontend
|
||
|
||
### 5.1 Entry
|
||
|
||
* Sidebar「Website Management → Response Pages」: Error Page tab (`/responses`), edit page `/responses/error-page/edit`, preview page `/responses/error-page/preview`.
|
||
|
||
### 5.2 Page Structure
|
||
|
||
* Header note: takes effect after releasing via「Version Release」.
|
||
* **Switch + Tags Input** (shadcn-extension Tags Input: `@/components/ui/tags-input`): status code tags.
|
||
* **HTML editor area** +「Load default template」「Restore default (clear)」+ placeholder docs.
|
||
* **Client-side preview**: replace with sample `status=502`, `host=example.com` and preview in sandbox/iframe.
|
||
* Save: `OptionService.updateBatch`; permissions same as the performance tuning page (admin).
|
||
|
||
### 5.3 Component Dependencies
|
||
|
||
Tags Input and the HTML editor reuse existing shadcn/ui components, consistent with the existing UI style.
|
||
|
||
---
|
||
|
||
## 6. Data Flow
|
||
|
||
```text
|
||
Admin /responses (Error Page tab)
|
||
→ Option update-batch (validate tags & HTML)
|
||
→ w_system_configs
|
||
|
||
Release config version
|
||
→ snapshot writes OriginErrorPage*
|
||
→ render OpenResty conf + SupportFile
|
||
→ Agent pulls and reloads
|
||
|
||
Visitor requests a proxied domain
|
||
→ origin/gateway produces a matching status code
|
||
→ error_page → named location
|
||
→ replace placeholders, keep original status, return HTML
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Decision Record
|
||
|
||
| Decision | Choice | Reason |
|
||
| --- | --- | --- |
|
||
| Config scope | global | product requirement; simple implementation and ops |
|
||
| Storage | Option + config version | consistent with performance tuning, rollbackable |
|
||
| Status input | tags: single code and range | default whole 5xx, but can name 522 |
|
||
| Response status | keep original | correct for monitoring/SEO/client semantics |
|
||
| Runtime replacement | internal + lightweight template replacement | status differs per request |
|
||
| Customization | online HTML | flexible without a file-upload chain |
|