Webhook
内容发布时 Atlas 发送给您网站的带签名通知,使您能够精确刷新受影响的页面。
本页面由英文翻译而来。如有任何差异,以英文版本为准。 阅读英文版
在 Studio 的 Integrations → Webhooks 下创建 Webhook。每个 Webhook 都有一个 HTTPS URL、它所接收的事件,以及以 whsec_ 开头的签名密钥(只显示一次)。
Atlas 只向公共 HTTPS 地址投递。私有网络地址会被拒绝;只有在开发期间向 localhost 才允许使用普通 HTTP。
POST https://your-site.example/api/atlas/webhookContent-Type: application/jsonX-Atlas-Event: content.page.publishedX-Atlas-Delivery: <unique delivery id>X-Atlas-Signature: t=1761210000,v1=5f2b…验证每个请求
Section titled “验证每个请求”import { createHmac, timingSafeEqual } from 'node:crypto';import { revalidatePath, revalidateTag } from 'next/cache';
const seen = new Set<string>(); // use a shared store (Redis, KV) when you run several instances
export async function POST(request: Request) { const body = await request.text(); // the raw body, before any JSON parsing const header = request.headers.get('x-atlas-signature') ?? ''; const parts = Object.fromEntries(header.split(',').map((part) => part.split('=', 2))); const timestamp = Number(parts.t);
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return new Response(null, { status: 400 });
const expected = createHmac('sha256', process.env.ATLAS_WEBHOOK_SECRET!) .update(`${timestamp}.${body}`) .digest(); const given = Buffer.from(String(parts.v1 ?? ''), 'hex'); if (given.length !== expected.length || !timingSafeEqual(given, expected)) { return new Response(null, { status: 401 }); }
const delivery = request.headers.get('x-atlas-delivery') ?? ''; if (seen.has(delivery)) return new Response(null, { status: 200 }); // already handled seen.add(delivery);
const payload = JSON.parse(body); // e.g. { pageId, route, revision } for content.page.published if (typeof payload.route === 'string') revalidatePath(payload.route); else revalidateTag('atlas'); // entries, globals, translations: refresh everything tagged 'atlas' return new Response(null, { status: 200 });}检查步骤依次为:
- 使用原始请求体。
- 拒绝时间戳早于 5 分钟的请求。
- 使用您的签名密钥计算
HMAC-SHA256("<t>.<raw body>"),并以恒定时间进行比较。 - 忽略重复的
X-Atlas-Deliveryid。
请记录事件类型和投递 id,切勿记录请求体或密钥。
请求体就是事件的载荷。对于 content.page.published,它是 { "pageId", "route", "revision" }。事件类型位于 X-Atlas-Event 标头中。
Webhook 只需在开发环境中设置一次,也会接收来自线上网站的事件。每个载荷都带有 environment:"development" 或 "production",因此您可以区分它们。
| 事件 | 触发时机 |
|---|---|
content.page.published |
页面被发布或回滚 |
content.page.unpublished |
页面从网站下线 |
content.page.route.changed |
页面迁移到新地址(同时添加一条重定向) |
content.entry.published |
集合条目被发布 |
content.entry.unpublished |
集合条目从网站下线 |
content.global.published |
页眉、页脚或其他全局内容被发布 |
content.translation.published |
译文被发布 |
contract.activated |
新的站点契约被激活 |
seo.redirects.changed |
重定向发生变化 |
media.asset.uploaded |
媒体文件被上传 |
form.published |
表单被发布 |
form.submission.accepted |
表单提交被接受 |
lead.created |
收到新线索(仅含 id,不含个人数据) |
lead.merged |
线索被合并到另一条线索(仅含 id) |
bot.published |
聊天机器人被发布 |
Atlas 最多等待您的响应 10 秒,并且不会跟随重定向。请使用 Studio 的投递历史查看载荷和失败情况。