博客在线写作入口实现
给博客加一个在线编辑入口
之前写博客,总得先打开本机的项目,写 Markdown,构建,再 commit、push。
流程并不复杂,但每次只是想写两句话,却得先把自己切换到“维护网站”的状态。电脑不在身边的时候,就更懒得动了。
所以这次干脆给博客加了一个网页写作入口。
GitHub Pages 负责展示,Cloudflare 负责处理请求
博客原来的架构没有换,仍然是 Hexo + Butterfly + GitHub Pages。
问题在于,GitHub Pages 是静态托管,不能替我保管登录密钥,也不能直接承担安全的授权和发布逻辑。
于是中间加了一个 Cloudflare Worker。
整条路径大概是这样:
1 | 浏览器里的 Markdown 编辑器 |
前面是写作,后面仍然是原来的静态博客。
GitHub 权限实现
权限是这次不能糊弄的部分。
一个公开的编辑页面,可以允许别人打开,但不能因为别人也有 GitHub 账号,就让他往我的博客里面塞文章。
这里用了 GitHub App,而不是让人在网页里粘贴个人访问令牌。App 只安装到博客仓库,申请内容读写和构建状态只读权限,不需要碰其他仓库,更不需要访问 private 仓库。
登录之后,服务端还会检查 GitHub 账号的数字 ID 和登录名。不是指定的作者,就不会放行。
授权流程使用 PKCE 和随机 state。GitHub token 不暴露给网页 JavaScript,也不放进 localStorage,而是保存在加密的 HttpOnly Cookie 中,并设置过期时间。
发布请求还要同时通过来源和 CSRF 校验。
发布流程
编辑器里可以填标题、分类、标签、摘要和 Markdown。新文章的网址会自动生成,也可以自己改;编辑旧文章时,则保留原来的网址和首次发布日期。
封面有两个来源:
- 从仓库已经公开的图片中选择;
- 从本机上传一张新图片。
上传的图片会先在浏览器里缩放、重新编码成 WebP,不把原始大图和它附带的元数据直接搬进仓库。
真正发布时,Worker 通过 GitHub Git Data API 创建 blob、tree 和 commit,最后更新 main 分支。
如果有新封面,文章、封面和图片白名单会放进同一个提交。
服务端也不接受任意文件路径。编辑器能改的是文章和规定目录里的封面,不是整个仓库。
互斥锁
还有一个很容易被忽略的情况:同一篇文章,在两个窗口里都打开了。
如果后保存的窗口直接覆盖前一个窗口,写了半天的东西可能就没了。
所以加载文章时,会记录对应的 blob SHA。发布前再核对一次:仓库里的版本如果已经变了,就拒绝覆盖,让人先保留草稿,再重新加载合并。
最后更新分支时也不使用强制更新。即使是在发布过程中,仓库又出现了新的提交,也不能直接把它推掉。
发布流程
这次还把 GitHub Pages 的发布源切到了 GitHub Actions。
以前需要本机生成 HTML,再把静态结果提交上去。现在网页只要把源文件写入仓库,工作流就会自动安装依赖、运行测试、构建 Hexo、检查网站,再部署到 Pages。
编辑器会显示构建进度,但“提交成功”和“已经上线”仍然是两件事。构建如果失败,提交还在,可以沿着日志继续找问题,而不是让页面假装什么都完成了。
草稿则留在当前浏览器,也可以导出 Markdown。没有点发布之前,它不会自动进入公开仓库。
最后
这次没有把博客做成一个很大的内容管理系统。
想到一句话的时候,能直接打开网页写下来,最近自己的各种想法可能比较多,能随时写写也不错。
不过我感觉我可以以后在这边更文章了?
没能让cloudflare大人用出全力真是抱歉。










