配信の挙動
プロバイダーの公式ドキュメントから読み取っています(最終確認 2026-08-06)。プロバイダーが数値を示していない項目には、この表も数値を載せていません。
| 応答期限 | 10 秒 |
|---|---|
| リトライ | なし。GitHub は失敗した配信を自動ではリトライしない |
| 打ち切り | 無効化なし。配信は 3 日間は手動で再配信でき、その後は記録が消える |
| 出典 | https://docs.github.com/en/webhooks/using-webhooks/best-practices-for-using-webhooks |
署名
ドキュメントを読んだだけではなく、テストスイートで裏付けた動作する検証コードで確認しています。最終検証日は 2026-08-20 です。
| アルゴリズム | HMAC-SHA256 |
|---|---|
| 署名対象 | raw body |
| エンコード | hex |
| ヘッダー | x-hub-signature-256 = sha256=hex |
| 許容範囲 | 適用なし |
検証する
JSON としてパースする前の生のリクエストボディを、バイト単位でそのまま使います。フレームワークがペイロードを再シリアライズした時点で、このページのどの方式も検証に失敗します。
const crypto = require("node:crypto");
// x-hub-signature-256: "sha256=" + hex(HMAC-SHA256(secret, raw body))
const expected =
"sha256=" +
crypto.createHmac("sha256", webhookSecret).update(rawBody).digest("hex");
const received = Buffer.from(req.headers["x-hub-signature-256"] ?? "");
const wanted = Buffer.from(expected);
// timingSafeEqual throws on a length mismatch, so check that first.
const valid =
received.length === wanted.length && crypto.timingSafeEqual(received, wanted);落とし穴
試行は 1 回きりです。この一覧の他の送信元はすべて自動でリトライしますが、GitHub はしません。そのため 30 秒のデプロイの間に届いたイベントは、やり直しの機会なく失われます。Redeliver(再配信)ボタンと Redelivery API は、配信ごとに手動で、3 日間だけ使えます。それを過ぎると記録そのものが消えます。
あわせて読む
AnyHook は、GitHub から受信するエンドポイントの手前に入ります。約 1 秒で応答し、サーバーがダウンしていれば独自のスケジュールでリトライします。すべてのイベントは再送できる状態で保存されます。 変えるのは URL 1 つだけで、コードはそのままです。