自托管 lavish-axi 分享后端:Cloudflare Worker 参考实现与 API 契约指南
【免费下载链接】lavish-axiHTML is the new markdown. Lavish is the new editor for your HTML artifacts.项目地址: https://gitcode.com/gh_mirrors/la/lavish-axi
lavish-axi是一个本地优先的 HTML 工件编辑器,它的lavish-axi share命令默认把 HTML 发布到第三方托管服务 ht-ml.app。如果你希望分享页面完全托管在自己可控的服务器上——数据不出内网、域名自己说了算——本文带你完整走一遍:官方 API 契约长什么样、一个环境变量如何切换到自己的后端、以及官方文档里给出的 Cloudflare Worker 参考实现到底解决了哪些问题。
一、先搞懂 share 命令在做什么 🚀
在执行lavish-axi share <html-file>时,CLI 会做三件事:
- 打包:把 HTML 里的本地图片、CSS、脚本内联进单个文件(远程 CDN 引用保持原样),逻辑与
export完全一致,见 src/export-bundle.js; - 发布:把整页 HTML 以 JSON 形式
POST到分享后端,默认目标是 ht-ml.app; - 回执:后端返回访问 URL 和一个只显示一次的秘密
update_key,它是日后更新、锁页、撤稿的唯一凭据。
发布出来的 HTML 可以携带图表、白板和交互动画——比如下面这个带 Mermaid 流程图和会话面板的工件,右侧面板可以直接向 Agent 发送修改意见:
整个发布通道的源码在 src/html-app.js,测试在 test/html-app.test.js,行为边界都写得清清楚楚。
二、API 契约:只有 2 个端点 🔌
官方契约文档是 docs/self-hosting-share.md,你的后端只需要实现两个接口,两个请求都在 30 秒超时内完成:
| 操作 | 端点 | 认证方式 |
|---|---|---|
| 创建页面 | POST /v1/sites | Authorization: Bearer <token>(仅当你配置了 token) |
| 重新发布 / 撤稿 | PUT /v1/sites/{site_id} | Authorization: Bearer <update_key> |
创建请求的 body 很简单:
{ "html_content": "<完整的内联 HTML>", "password": "<可选,--private 或 --password 时携带>" }响应必须至少包含url和update_key,缺失任一个share命令都会直接报错:
{ "url": "https://plans.example.com/abc123", "update_key": "<秘密,只显示一次>", "site_id": "abc123", "status": "published" }几个容易踩的契约细节:
site_id会拼进 URL 路径,所以只能取A-Za-z0-9._-字符集,全点的 id 会被拒绝;- 重新发布用
update_key认证,不认创建时的 token,--token在重发时会被显式拒绝; - 密码无法删除——
password缺省时保留原密码,提供时设置或轮换,永远不要回传空字符串; - 没有 DELETE:
--unpublish实际是一次PUT,用占位页替换原内容并锁上一个随机密码。
三、一个环境变量切换到自己的后端 ⚙️
配置只有两个变量,定义见 docs/self-hosting-share.md#L7-L12:
| 环境变量 | 作用 |
|---|---|
LAVISH_AXI_HTML_APP_API_URL | 你的分享后端 Base URL,默认https://api.ht-ml.app,结尾斜杠会被自动去掉 |
LAVISH_AXI_HTML_APP_TOKEN | 可选 Bearer token,仅用于POST /v1/sites,也可用--token按次传入 |
设置示例:
export LAVISH_AXI_HTML_APP_API_URL="https://share-api.your-domain.com" export LAVISH_AXI_HTML_APP_TOKEN="s3cret-token" lavish-axi share plan.html就这么简单——CLI 侧零改动,所有 URL 拼接、update_key校验、不完整响应检测都由 src/html-app.js 统一处理。
四、Cloudflare Worker 参考实现 👷
官方文档内置了一份最小可用的 Worker(docs/self-hosting-share.md#L83-L124),核心逻辑压缩后如下:
export default { async fetch(req, env) { const { pathname } = new URL(req.url); const bearer = (req.headers.get("authorization") || "").replace(/^Bearer /, ""); // 创建:必须校验 token,否则任何人都能在你的域名上托管任意 HTML if (req.method === "POST" && pathname === "/v1/sites") { if (bearer !== env.SHARE_TOKEN) return new Response("Unauthorized", { status: 401 }); const { html_content, password } = await req.json(); const id = crypto.randomUUID().slice(0, 8); const update_key = crypto.randomUUID(); await env.SITES.put(id, JSON.stringify({ html_content, password: password || null, update_key })); return Response.json({ url: `https://${env.VIEW_HOST}/${id}`, update_key, site_id: id, status: "published" }); } // 重发 / 撤稿:update_key 是页面唯一凭据,不匹配必须 401,绝不静默忽略 const site = pathname.startsWith("/v1/sites/") && pathname.slice("/v1/sites/".length); if (req.method === "PUT" && site && !site.includes("/")) { const stored = await env.SITES.get(site, "json"); if (!stored || bearer !== stored.update_key) return new Response("Unauthorized", { status: 401 }); const { html_content, password } = await req.json(); await env.SITES.put(site, JSON.stringify({ ...stored, html_content, password: password || stored.password })); return Response.json({ url: `https://${env.VIEW_HOST}/${site}`, site_id: site, status: "published" }); } return new Response("Not found", { status: 404 }); }, };配套只需三件事:
- 在 KV(
SITES)里存{html_content, password, update_key}; - 配置
VIEW_HOST环境变量作为访问域名前缀; - 把查看器(
GET /:id)部署在独立域名,并在返回 HTML 前强制执行存储的password。
五、安全清单:3 条铁律 🔒
- 用 token 守住
POST /v1/sites——未鉴权的创建端点等于允许任何人挂钓鱼页面到你的域名下; - 隔离查看器来源——发布的工件自带 JavaScript,务必跑在专用域名 + 严格 CSP 下,别让它摸到你主站的 Cookie;
- 尊重
password字段——存在密码的页面必须先验证密码再吐出 HTML。
另外两个行为提醒:页面从公开变为私有不是瞬时的(CDN 缓存可能继续放几分钟),而update_key只返回一次,丢了这页就再也没法更新——参考实现的crypto.randomUUID()正是为此而生。
六、延伸阅读 📚
| 资料 | 路径 |
|---|---|
| 自托管完整契约 | docs/self-hosting-share.md |
| 发布/更新传输层源码 | src/html-app.js |
| 分享密码生成(防误输字符集) | src/share-password.js |
| share 命令实现 | src/cli.js |
想动手试的话,先克隆仓库读一遍契约文档,再按 Worker 参考实现部署一个最小心跳服务,用LAVISH_AXI_HTML_APP_API_URL指过去,一条lavish-axi share就能验证整条链路。
【免费下载链接】lavish-axiHTML is the new markdown. Lavish is the new editor for your HTML artifacts.项目地址: https://gitcode.com/gh_mirrors/la/lavish-axi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考