notify-relay

通知中转服务 · 密钥只在服务端 · Cloudflare Access 鉴权

其他应用通过本服务发送通知,底层的钉钉 / Bark 密钥保存在 Cloudflare Secrets Store, 调用方永远拿不到。鉴权由 Cloudflare Access(service token)在边缘完成。

鉴权

每个请求需带 service token 两个头:

CF-Access-Client-Id: <your-client-id>
CF-Access-Client-Secret: <your-client-secret>

token 由 Cloudflare Zero Trust 签发,每个调用方一个,可单独吊销。

接口

方法路径请求体响应
GET/health—{"ok":true}
POST/dingtalk{title?, body}{"ok":true}
POST/bark{title?, body, sound?, group?, url?, level?}{"ok":true}

body 必填;title 可选。失败返回 {"ok":false} + 对应 4xx/5xx 状态码,不回显任何配置细节。

示例

钉钉:

curl -X POST https://notify.example.com/dingtalk \
  -H "CF-Access-Client-Id: $CF_ID" \
  -H "CF-Access-Client-Secret: $CF_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"title":"部署完成","body":"web-app 已上线"}'

Bark:

curl -X POST https://notify.example.com/bark \
  -H "CF-Access-Client-Id: $CF_ID" \
  -H "CF-Access-Client-Secret: $CF_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"title":"提醒","body":"该喝水了","sound":"glass","group":"daily"}'

Node.js(其他 Worker / 本地脚本):

await fetch("https://notify.example.com/bark", {
  method: "POST",
  headers: {
    "CF-Access-Client-Id": process.env.CF_ID,
    "CF-Access-Client-Secret": process.env.CF_SECRET,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ title: "hi", body: "hello from script" }),
});

仓库:git@github.com:danny-plus/notify-relay.git