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