Skip to main content

接口分组

所有 API 由 functions/_lib/ 下的同一份核心代码实现,被 Cloudflare Workers(worker.js 路由分发)与 Cloudflare Pages Functions(functions/api/ 下的路由文件)复用。部署形态会决定部分端点的可用性(见下方「Workers 与 Pages 的差异」)。
各端点的完整请求/响应示例见「API 参考」分组下的对应页面。

Workers 与 Pages 的差异

Workers AI 仍然是 Workers 专属绑定:wrangler.toml(Pages)没有 [ai] 配置,因此 Pages 部署下 /api/ai/* 恒为 404;前端会自动隐藏 AI 入口。音乐、媒体等其余接口已在 Pages Functions 中补齐。
未知的 /api/* 路径一律返回 JSON 404,绝不回退到 index.html(避免调用方拿到 HTML 再 .json() 抛出难懂的解析错误)。Pages 侧的兜底响应带一段 hint:

鉴权方式

所有需要鉴权的接口通过 HTTP Header 传递会话令牌:
令牌由 /api/admin/login 签发(32 字节随机数 → 64 位十六进制字符串),有效期 7 天,存于 D1 admin_sessions 表;前端存 localStorage 并由 apiFetch 自动附带。为兼容旧配置,写鉴权仍接受环境变量 BLOG_WRITE_TOKEN 作为静态长令牌。
浏览器直传 R2 时,预签名 PUT 的签名头包含 content-type,因此浏览器必须原样发送 Content-Type,且 R2 桶 CORS 的 AllowedHeaders 必须包含 Content-Type(缺失会让浏览器报预检失败)。

错误码约定

错误响应统一格式:
前端 apiFetch 会把 error 字段解析为异常消息直接展示给用户(如「请勿重复发送相同内容」),不再只显示 HTTP 状态码。

CORS 与缓存

  • CORS:配置 SITE_URL 后只允许「站点来源 + 请求自身来源」;env.SITE_URL 与当前请求 origin 都不匹配时不返回 Access-Control-Allow-Origin,浏览器会拦下跨站读取。未配置 SITE_URL 时 fail-closed(不返回 ACAO),不再是旧版的「回显任意来源」。
  • 允许的请求头:Content-Type、Authorization、X-Setup-Key;允许的方法:GET, POST, PUT, DELETE, OPTIONS;响应带 Vary: Origin,避免跨域缓存命中错误副本。
  • 安全响应头:API 与静态响应统一注入 Content-Security-Policy、X-Content-Type-Options: nosniff、Referrer-Policy: strict-origin-when-cross-origin、X-Frame-Options: SAMEORIGIN、Cross-Origin-Opener-Policy: same-origin。
  • 客户端 IP:所有按 IP 的限流与去重只信任 Cloudflare 注入的 CF-Connecting-IP,不读可被伪造的 X-Forwarded-For。
  • 缓存:只读接口 public, s-maxage=60, stale-while-revalidate=300,RSS/Sitemap public, s-maxage=300, stale-while-revalidate=600,评论列表与全部写操作 no-store。写操作后按 Cache-Tag(posts / feed / sitemap / post:<id> / stats:<id>)主动清边缘缓存,需要 CF_API_TOKEN + CF_ZONE_ID。详见项目架构。
  • 静态资源:带 ?v= 版本号或位于 /fonts/、/flags/、/libs/smoji/ 下的文件 max-age=31536000, immutable;其他带扩展名的静态文件 max-age=3600, stale-while-revalidate=86400;无扩展名的 HTML 入口 no-cache。