Repository navigation
feat(cloudflare): serve open.longbridge.com from Cloudflare Pages - #1286
Conversation
Prepare the docs site to replace the open.longbridge.com nginx server with Cloudflare Pages. Merging changes nothing for users until DNS moves; nginx keeps serving .com (before cutover), .cn and open.longbridge.xyz from OSS. Cloudflare track - functions/[[path]].ts: Pages Function ports every open.longbridge.com nginx rule in declaration order (login pages, locale llms, terminal proxy, trailing slash, /en, SPA forwarding, install 301/proxy, markdown negotiation, X-Frame-Options). Upstreams are picked per host from the SITES table. - public/_routes.json, public/_redirects, 404 page, canary-only robots. - release.yml deploys Cloudflare in its own job (ASSETS_DIR=_docs). - canary-cloudflare.yml publishes open-canary.longbridge.xyz from the canary branch. canary-aliyun.yml and oss-probe.yml are manual-only. - pack-skills.yml re-dispatches the Cloudflare builds after uploading zips. nginx (OSS) track stays byte-compatible - ASSETS_DIR picks the hashed asset dir: OSS builds keep /assets, Cloudflare builds use /_docs. - scripts/copy-routes.ts runs only in the OSS jobs, giving nginx the foo/index.html shape it reads. - OSS jobs assert both before uploading. Also: SEO metadata, locale sitemaps, .md links in llms.txt, skill zip packing, canary hostname rewrite. Full record and verification in docs/superpowers/plans/2026-09-16-openapi-nginx-decommission.md (§15). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| // 一致);'directory' 产 `foo/index.html` → 规范 URL 变成 `/foo/`,`/foo` 反被 308 | ||
| // 到带尾斜杠版本,而 canonical 仍写无尾斜杠,两者自相矛盾(实测见方案 §15.9)。 | ||
| // - 阿里云轨(.cn)将来由 OSS 静态网站托管直接承载时才需要 'directory',配合 | ||
| // 「子目录首页 + 文件404规则=Index」让 /foo 直接 200 且地址栏不变。届时在那条 |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| // 「子目录首页 + 文件404规则=Index」让 /foo 直接 200 且地址栏不变。届时在那条 | |
| // 「子目录首页 + 文件 404 规则=Index」让 /foo 直接 200 且地址栏不变。届时在那条 |
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : String(err) | ||
| console.warn(`[prebuild-skills] git operation failed (${message}) — skipping zip`) | ||
| console.warn(`[prebuild-skills] git 失败(${err instanceof Error ? err.message : err}) — 跳过 zip`) |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| console.warn(`[prebuild-skills] git 失败(${err instanceof Error ? err.message : err}) — 跳过 zip`) | |
| console.warn(`[prebuild-skills] git 失败 (${err instanceof Error ? err.message : err}) — 跳过 zip`) |
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : String(err) | ||
| console.warn(`[prebuild-skills] zip failed (${message}) — skipping`) | ||
| console.warn(`[prebuild-skills] skills.zip 失败(${err instanceof Error ? err.message : err})`) |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| console.warn(`[prebuild-skills] skills.zip 失败(${err instanceof Error ? err.message : err})`) | |
| console.warn(`[prebuild-skills] skills.zip 失败 (${err instanceof Error ? err.message : err})`) |
| writeZip(path.join(DIST_SKILL_DIR, 'longbridge-all.zip'), SKILLS_SUBDIR, ['.']) | ||
| written.push('longbridge-all.zip') | ||
| } catch (err) { | ||
| console.warn(`[prebuild-skills] longbridge-all.zip 失败(${err instanceof Error ? err.message : err})`) |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| console.warn(`[prebuild-skills] longbridge-all.zip 失败(${err instanceof Error ? err.message : err})`) | |
| console.warn(`[prebuild-skills] longbridge-all.zip 失败 (${err instanceof Error ? err.message : err})`) |
| writeZip(path.join(DIST_SKILL_DIR, `${entry.name}.zip`), SKILLS_SUBDIR, [entry.name]) | ||
| written.push(`${entry.name}.zip`) | ||
| } catch (err) { | ||
| console.warn(`[prebuild-skills] ${entry.name}.zip 失败(${err instanceof Error ? err.message : err})`) |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| console.warn(`[prebuild-skills] ${entry.name}.zip 失败(${err instanceof Error ? err.message : err})`) | |
| console.warn(`[prebuild-skills] ${entry.name}.zip 失败 (${err instanceof Error ? err.message : err})`) |
| |---|---|---|---| | ||
| | 1 | 链路为 client→traefik→nginx→阿里云CDN→OSS | runtime @响应头含 `via: ens-cache*`/`x-oss-*`,`X-Frame-Options`/`X-Robots-Tag` 由 nginx 注入 | verified | | ||
| | 2 | `lb-assets` 桶为公共读 | runtime @OSS 直连 200;对照 `lb-assets-hk` → 403 | verified | | ||
| | 3 | 阿里云 CDN「访问URL重写」break=内部改写、Redirect=302/303/307,支持 PCRE 与 `$1`,单域名上限 50 条 | 阿里云文档 120538 | verified (doc) | |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| | 3 | 阿里云 CDN「访问URL重写」break=内部改写、Redirect=302/303/307,支持 PCRE 与 `$1`,单域名上限 50 条 | 阿里云文档 120538 | verified (doc) | | |
| | 3 | 阿里云 CDN「访问 URL 重写」break=内部改写、Redirect=302/303/307,支持 PCRE 与 `$1`,单域名上限 50 条 | 阿里云文档 120538 | verified (doc) | |
| | 22 | 其中 `longbridge-terminal/install(.ps1)` 被 10 处文档引用;8 个 svg 零引用 | code @`rg` 复核 | verified | | ||
| | 23 | `~* \.md$` / `~* \.zip$` 是 longbridge 侧的**按扩展名通配**规则,longportapp 侧没有 | code @`_release.conf:71,77`;runtime @longportapp `/skill/longbridge.zip` → 404 | verified | | ||
| | 24 | 往三个前缀写入的流水线共 6 条(5 活跃 + 1 遗留) | code @本地 52 clone `rg --hidden`;**仅覆盖本地 clone** | verified(范围受限) | | ||
| | 25 | OSS 静态网站托管「文件404规则=Index」对不带尾斜杠路径返回 200 且地址栏不变 | 阿里云 OSS 文档 | verified (doc) | |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| | 25 | OSS 静态网站托管「文件404规则=Index」对不带尾斜杠路径返回 200 且地址栏不变 | 阿里云 OSS 文档 | verified (doc) | | |
| | 25 | OSS 静态网站托管「文件 404 规则=Index」对不带尾斜杠路径返回 200 且地址栏不变 | 阿里云 OSS 文档 | verified (doc) | |
| | 26 | CDN 私有 Bucket 回源与 OSS 默认首页互斥 → **新桶必须公共读** | 阿里云文档 + 社区整理 | verified (doc) | | ||
| | 27 | 阿里云 CDN 重写正则是否支持负向先行断言(`.cn` catch-all 302 需排除 `/docs` `/skill`) | — | **to measure**(建桶时) | | ||
| | 28 | `cross-env A=1 cmd1 && cmd2` 中 A **不会**传给 cmd2 | runtime @直接实测:`cmd1: yes` / `cmd2: undefined` | verified | | ||
| | 29 | 因 #28,`build:release`/`build:canary` 的 `astro build` 从未拿到 `VITE_API_BASE_URL`/`VITE_SITE_HOSTNAME`/`NODE_OPTIONS`;`build:cn` 因有 `sh -c` 包裹而正常 | runtime @对照实验:cn 桶 llms.txt 318×`open.longbridge.cn`(对) vs .com 桶 318×`open.longportapp.com`(错) | verified | |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| | 29 | 因 #28,`build:release`/`build:canary` 的 `astro build` 从未拿到 `VITE_API_BASE_URL`/`VITE_SITE_HOSTNAME`/`NODE_OPTIONS`;`build:cn` 因有 `sh -c` 包裹而正常 | runtime @对照实验:cn 桶 llms.txt 318×`open.longbridge.cn`(对) vs .com 桶 318×`open.longportapp.com`(错) | verified | | |
| | 29 | 因 #28,`build:release`/`build:canary` 的 `astro build` 从未拿到 `VITE_API_BASE_URL`/`VITE_SITE_HOSTNAME`/`NODE_OPTIONS`;`build:cn` 因有 `sh -c` 包裹而正常 | runtime @对照实验�(对)vs .com 桶 318×n.longbridge.cn`(对) vs .com 桶 318×`open.longportapp.com`(错) | verified | |
|
|
||
| **响应头**:longbridge 侧 `X-Frame-Options: SAMEORIGIN`;longportapp 侧 `X-Robots-Tag: noindex, nofollow`;**验证域名**额外加 `X-Robots-Tag: noindex, nofollow` 防收录。 | ||
|
|
||
| **规则 7 与 OSS 的配合**:先 302 掉尾斜杠,再由「文件404规则=Index」处理无尾斜杠路径。`/` 本身不匹配规则 7(要求 `/` 前至少一字符),走 OSS 默认首页。 |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| **规则 7 与 OSS 的配合**:先 302 掉尾斜杠,再由「文件404规则=Index」处理无尾斜杠路径。`/` 本身不匹配规则 7(要求 `/` 前至少一字符),走 OSS 默认首页。 | |
| **规则 7 与 OS*:先 302 掉尾斜杠,再由「文件 404 规则=Index」处理无尾斜杠路径。杠路径。`/` 本身不匹配规则 7(要求 `/` 前至少一字符),走 OSS 默认首页。 |
| | 过滤参数 | **关闭**(query 要留给 `?invite-code=` 的 301) | | ||
| | 缓存 | 遵循源站(ossutil 上传时已按类型分组设好 Cache-Control) | | ||
|
|
||
| ### 14.3 访问URL重写(12 条,顺序即优先级) |
There was a problem hiding this comment.
🚫 [AutoCorrect Lint] <AutoCorrect> reported by reviewdog 🐶
| ### 14.3 访问URL重写(12 条,顺序即优先级) | |
| ### 14.3 访问 URL 重写(12 条,顺序即优先级) |
#1286 (Cloudflare Pages) was merged while **Check text autocorrect** was failing, so every PR opened since then fails the same 11 errors in files it doesn't touch — e.g. #1263 and #1289. This adds the CJK/ASCII spacing autocorrect asks for, in exactly the 11 places the CI job reports: - `astro.config.ts` (1) - `src/integrations/prebuild-skills.ts` (4) — log message strings only, no behavior change - `docs/superpowers/plans/2026-09-16-openapi-nginx-decommission.md` (6) Once this is merged, re-running the autocorrect check on #1263 / #1289 should pass, since PR checks run against the merge with `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Prepare the docs site to replace the open.longbridge.com nginx server with Cloudflare Pages. Merging changes nothing for users until DNS moves; nginx keeps serving .com (before cutover), .cn and open.longbridge.xyz from OSS.
Cloudflare track
nginx (OSS) track stays byte-compatible
Also: SEO metadata, locale sitemaps, .md links in llms.txt, skill zip packing, canary hostname rewrite. Full record and verification in docs/superpowers/plans/2026-09-16-openapi-nginx-decommission.md (§15).