CFCF Static Export ProDEMO

用 REST API 接入任何编辑器

为什么是 WP REST

第三方编辑器(Obsidian、Ulysses、脚本)大多已经支持 WordPress REST。与其为每个工具写适配,不如实现它的一个子集:

方法 路径 用途
GET /wp-json/wp/v2/posts 列表
GET /wp-json/wp/v2/posts/<id> 单篇
POST /wp-json/wp/v2/posts 新建
PUT/PATCH /wp-json/wp/v2/posts/<id> 更新
GET /wp-json/wp/v2/categories 分类
GET /wp-json/wp/v2/tags 标签
POST /wp-json/wp/v2/media 上传媒体

认证

用 应用密码 + Basic Auth:

curl -u 'admin:xxxx xxxx xxxx xxxx' \
  https://example.com/wp-json/wp/v2/posts

应用密码在后台「用户 → 应用密码」生成,明文只显示一次。

不支持 Bearer Token —— JWT 是后台 SPA 用的,第三方入口刻意分开,避免把管理权限暴露给编辑器。

内容格式

请求体里带 content_format: "md" 时,正文按 Markdown 原稿存储,渲染出口用 marked 转 HTML。

不带这个字段则按 HTML 处理,入库前会做一次净化。

防覆盖

这是设计里最容易被忽略的一块。

WordPress 的 save_post 会自动导出,导出 SQL 如果无脑 INSERT OR REPLACE,就会把 Worker 端用 md 写的文章覆盖成 HTML。

现在的规则是:content_format='md' 视为"线上托管"标记,WP 导出时遇到 md 文章直接跳过(不写 D1、不上传 R2)。

含义:

  • 从 Obsidian / REST 写入的文章,永远归 CMS 管;
  • 想让 WordPress 接管,需要先在 CMS 里把它转成 HTML(或删掉重建);
  • 这是一条单向规则,刻意不做"自动合并"。

幂等

  • 新建时如果 slug 冲突,会自动追加 -2、-3;
  • 更新按 wp_id 定位,重复提交同一篇不会产生副本;
  • 媒体上传按文件名 + 日期目录存放,重复上传会覆盖同名文件。

一个最小示例

curl -X POST https://example.com/wp-json/wp/v2/posts \
  -u 'admin:app-password' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "从脚本发布",
    "slug": "from-script",
    "status": "draft",
    "content_format": "md",
    "content": "## Hello\n\n这是正文。",
    "categories": ["guide"],
    "tags": ["api"]
  }'

返回的 id 就是 wp_id,后续更新用它。

安全建议

  • 应用密码只给需要的权限,不要复用登录密码;
  • 生产环境建议加 IP 白名单或 Cloudflare Access;
  • 写入口有 IP 限流,但它不是防暴力破解的完整方案;
  • 定期在后台清理不再使用的应用密码。

发表评论

邮箱不会被公开。带 * 的为必填项。