想法
有时候觉得分享文章的时候默认的连接比较长
正好手上有短域名部署了Sink短链服务
想到可以通过云函数功能配合Webhook事件来请求Sink的API生成短链,并用于文章分享
Mix-space 后端部分
1.创建 Function
在 Mix-space后台-附加功能-配置与云函数新增一个函数
- 名称:
sink - 引用:
shiro - 类型:
Function - Secret 环境变量:
| 名称 | 示例值 | 说明 |
|---|---|---|
| blog_url | https://exmaple.com | 博客地址,结尾不加/ |
| sink_hostname | sink.cool | Sink实例地址,不加https://前缀,结尾不加/ |
| sink_token | 123456 | Sink的NUXT_SITE_TOKEN,用于请求API时鉴权 |
| webhook_secret | 123456 | 自己填入一个密匙,用于Webhook请求鉴权,在后面添加Webhook时会用上 |
在编辑器中填入以下内容:
设计逻辑
最开始计划的逻辑是slug留空给sink生成,这样能保证短链尽可能短,并且不会重复。
但是根据 Sink API 文档 可知,在请求删除一个短链时请求体参数需要slug,虽然可以先 LIST 找到 slug 再 DELETE,但是在短链变多后会变得很麻烦,LIST 只能分页查询。
因此需要能根据文章的唯一 _id 反推 slug。
_id实际上是 MongoDB 的 ObjectId。它是一个 24 位的十六进制字符串。前 8 位:是时间戳(精确到秒)。由文章创建时间决定。中间 10 位:是机器标识码和进程 ID(通常是随机生成的)。最后 6 位:是一个自增计数器(每次插入新数据时加 1)。
因此,短链生成的逻辑是:
1. 在计算出的4位前面加上 p 或 n 用于标识 post或note ,最终得到的slug形如 pabva 和 n1afc
Note为什么不直接取id的后四位?
id是一串16进制字符,那么它的命名空间只有0-9,a-f,这导致命名空间大幅减少,使得两篇文章slug重复的可能性增大,并且也不够美观。
当前方案slug重复的可能性有多大?
理论上存在,但对于个人博客来说,实际重复风险极低,基本可以忽略不计。
数学原理: Base36 包含 36 个字符(0-9,a-z)。截取最后 4 位,意味着共有 364 = 1,679,616(约 167 万)种唯一的组合。底层机制:MongoDB ID 的尾部是一个严格自增的计数器。当你截取转换后的后 4 位时,实际上是在做类似取模的循环。这意味着,除非博客文章和日记总数达到 167 万篇,否则在单台服务器上几乎不可能发生“转了一圈又撞上”的情况。
2.添加Webhook
在 附加功能-Webhooks-添加Webhook
- Payload URL:
https://example.com/api/v2/fn/shiro/sink?secret=<YOUR_WEBHOOK_TOKEN> - Secret 留空
(因为我似乎发现填写了此值也会显示"未配置Secret",故弃用,直接填在URL后面) - 触发事件:
POST_CREEATPOST_DELETENOTE_CREATNOTE_DELETE - 触发范围:系统事件
- 启用状态:启用
Note点击
发送测试会提示失败,因为测试的payload与实际payload不同,实际使用时不会报错。
新建一篇文章测试,点击右上角发布,查看webhook日志,在Response中有以下字段,代表创建短链成功:
3.前端获取短链
云函数中定义了一个API,在浏览器中输入地址可以获取已知id文章或手记的短链
GET https://example.com/api/v2/fn/shiro/sink?id=<id>&type=p
id为文章或手记的唯一idtype为类型,p代表posts,n代表notes
前端部分
由于更改的文件过多,本想通过提供github commit 链接做参考
但是我的仓库为了尊重原作者的工作也是 private,故给出以下详细提示词,可以使用 AI Agent 辅助完成修改
这个份提示词适用于单域名部署的Yohaku站点,如果你采用的是双域名的部署方式,可能需要修改 第 5 行 的描述
这是Codex GPT 5.5-Medium 给出的plan,执行修改后一次成功,您可以复制给AI Agent尝试