Files
WeChat-AI/docs/cloudflare.md
T

7.4 KiB
Raw Blame History

Cloudflare Business 缓存适配

本项目源站(Fastify Docker)已输出 Cloudflare 友好 的缓存头。你只需在 Cloudflare Dashboard 配好 Cache Rules 与区域级开关,即可最大化边缘命中。

相关代码:

能力 位置
HTML / OG 内存缓冲 + ETag apps/api/src/static-pages.ts, index.ts
统一 Cache-Control apps/api/src/cache-headers.ts
公开表情 CDN GET /cdn/s/:id?v={content_hash}
默认 API private, no-store apps/api/src/routes.ts onSend
CORS 白名单 CORS_ORIGINS + PUBLIC_BASE_URL

本阶段不上 R2;公开表情仍由源站 Redis blob 提供,靠边缘长缓存降压。


1. 源站响应策略(已实现)

路径 Cache-Control Cloudflare-CDN-Cache-Control 鉴权
/ /docs public, max-age=300 max-age=3600, swr=86400
/app /admin public, max-age=60 max-age=3600, swr=86400 无(壳静态;数据走 API
/og.jpg public, max-age=86400, immutable max-age=604800
/cdn/s/:id?v= public, max-age=31536000, immutable 同左 ;仅 public+approved+enabled
/api/v1/auth/config private, no-store 无(登录方式开关需实时)
/health no-store
其余 /api/v1/** private, no-store Cookie 会话
鉴权表情图 private, no-store 登录 / admin

HTML 带 ETag + Cache-Tag: html-shell;公开表情带 Cache-Tag: sticker-{id}(便于定向 Purge)。


2. DNS / SSL

  1. 域名 A/AAAA/CNAME 橙云代理到源站
  2. SSL/TLS → Full (strict)
  3. Always Use HTTPS = On
  4. 源站 .env
    • PUBLIC_BASE_URL=https://你的域名
    • COOKIE_SECURE=true
    • LINUXDO_REDIRECT_URI=https://你的域名/api/v1/auth/callback
    • 可选 CORS_ORIGINS=https://你的域名(默认已含 PUBLIC_BASE_URL origin

3. Cache Rules(按顺序创建,先匹配先生效)

路径:Caching → Cache RulesBusiness 推荐用 Cache Rules,而不是旧 Page Rules)。

Rule 1 — Bypass 动态 API

  • Name: bypass-api-private
  • When:
    starts_with(http.request.uri.path, "/api/v1/")
    或方法为 POST / PUT / PATCH / DELETE
  • Then: Cache eligibility = Bypass cache
  • Name: cache-html-shells
  • When:
    http.request.uri.path in {"/" "/app" "/docs" "/admin"}
  • Then:
    • Eligible for cache
    • Edge TTL: Respect origin(或 Override 1 hour
    • Browser TTL: Respect origin
    • Cache key → Ignore query string(可选)
    • Cookie handling → Ignore presence of cookies关键:否则带 wa_session 永远 MISS

Rule 3 — OG 图

  • Name: cache-og
  • When: http.request.uri.path eq "/og.jpg"
  • Then: Eligible for cacheEdge TTL Respect origin 或 7dIgnore cookies

Rule 4 — 公开表情 CDN

  • Name: cache-cdn-stickers
  • When: starts_with(http.request.uri.path, "/cdn/s/")
  • Then: Eligible for cacheEdge TTL Respect originIgnore cookies
  • Cache key 保留 query stringv= 内容哈希)

Rule 5 — auth/config 短缓存(已移除)

/api/v1/auth/config 现返回 no-store(登录方式开关需实时生效,不应缓存)。Cloudflare 默认尊重源站 Cache-Control,无 public 的响应不进共享缓存,故该路径无需任何缓存规则。

默认

未匹配规则时:尊重源站 Cache-Control;无 public 的不进共享缓存。


4. 区域级推荐(Business

设置 建议
HTTP/3 (QUIC) On
Brotli On
Tiered Cache On
Early Hints 可选(当前 HTML 内联,收益有限)
Auto Minify Off(避免改 HTML 导致 ETag 与部署不一致)
Rocket Loader Off
Polish 可选;若开 WebP,注意 Accept 变体,或只对 /cdn/s/*
Mirage 可选(移动列表)
Cache Reserve 可选(长尾表情)
Argo Smart Routing 源站距用户远时可选
WAF Managed Rules On
Rate limiting 建议:/api/v1/auth/*、try-chat、上传 POST
Bot Fight 按需;勿误伤 OAuth 回调

5. 部署后刷新缓存

变更 做法
新版本 HTMLapp/admin/docs/landing Purge by URL/ /app /docs /admin,或 Purge by Taghtml-shell
换图表情 无需 purge?v={content_hash} 自动新键
下架 / 拒绝公开表情 源站 404;边缘可能仍 HIT 至 TTL → Purge URL 或 Tag sticker-{id}
紧急全站 Purge Everything(会短暂升高源站压力)

API Purge 示例(可选):

# 需要 Zone ID + API Token (Cache Purge 权限)
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/purge_cache" \
  -H "Authorization: Bearer $CF_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"files":["https://你的域名/","https://你的域名/app","https://你的域名/docs","https://你的域名/admin"]}'

6. 验收 curl

HOST=https://你的域名

# HTML:第二次应 CF-Cache-Status: HIT(即使带假 cookie
curl -sI "$HOST/" | grep -iE 'cf-cache-status|cache-control|etag|content-encoding'
curl -sI "$HOST/app" -H "Cookie: wa_session=fake" | grep -i cf-cache-status

# 公开表情
curl -sI "$HOST/cdn/s/$STICKER_ID?v=$HASH" | grep -iE 'cf-cache-status|cache-control'
curl -sI "$HOST/cdn/s/$STICKER_ID?v=$HASH" | grep -i cf-cache-status   # HIT

# 私有 API
curl -sI "$HOST/api/v1/auth/me" -H "Cookie: wa_session=..." | grep -iE 'cache-control|cf-cache-status'
# 期望: private, no-storeDYNAMIC 或 BYPASS

# 压缩
curl -sI -H 'Accept-Encoding: br' "$HOST/app" | grep -i content-encoding

# 私有 / 未审表情不得公开
curl -sI "$HOST/cdn/s/$PRIVATE_ID"   # 404

Dashboard → Caching → Cache Analytics 可看 HIT 率。


7. 反代注意

  • 优先 CF 橙云 → 源站 443/8787,中间少一层
  • 多节点负载均衡:使用仓库内 cloudflare-worker/(静态 ORIGINS + 健康检查 + 轮询),主域名绑 Worker;详见 cloudflare-worker/README.md
  • 若 Nginx 仅 TLS 终结再反代 Node
    • 转发 HostX-Forwarded-ProtoCF-Connecting-IP
    • 不要强行剥掉 Accept-Encoding 导致双重压缩混乱
  • 源站健康检查:GET /health(进程)或 GET /health/ready(含 Redis,推荐给 LB
  • 应用侧 PUBLIC_BASE_URL 始终为主域名;源站 IP 不必暴露在后台 UI

8. 安全边界

  • /cdn/s/* visibility=publicreview_status=approvedenabled
  • 私有 / pending / rejected → 统一 404
  • 用户 JSON、admin、try-chat、OAuth callback 永不边缘共享缓存
  • 广场列表含 inLibrary 个性化,做公共 CDN 缓存(升级路径:拆无个性化的 public catalog API

9. 可选升级路径(未实现)

  1. 公开表情同步 R2 + 自定义域,源站只写 meta
  2. GET /api/v1/public/square/*inLibrary 的目录接口短缓存
  3. 内联 CSS/JS 拆出带 content-hash 的静态文件
  4. Cache Reserve + Image Resizing

详见主 README / 本文件与 docs/docker.md 交叉引用。