Cách GitHub gửi webhook

GitHub không bao giờ thử lại một lượt gửi thất bại, và bản ghi mất sau 3 ngày. Điều đó nghĩa là gì, định dạng chữ ký và code xác minh Node.

Hành vi gửi

Lấy từ tài liệu của chính hãng, kiểm tra lần cuối 2026-08-06. Hãng không nêu con số nào thì bảng này cũng không ghi.

Thời hạn phản hồi10 giây

Kiểm tra handler của bạn có phản hồi kịp không

Thử lạiKhông có. GitHub không tự thử lại các lượt gửi thất bại
Ngừng gửiKhông vô hiệu hóa. Bạn có thể gửi lại thủ công các lượt gửi trong 3 ngày, sau đó bản ghi không còn nữa
Nguồnhttps://docs.github.com/en/webhooks/using-webhooks/best-practices-for-using-webhooks

Chữ ký

Kiểm chứng bằng một bộ xác minh chạy thật, có bộ test chứng minh, chứ không đọc từ tài liệu. Kiểm chứng lần cuối 2026-08-20.

Thuật toánHMAC-SHA256
Payload được kýraw body
Encodinghex
Headerx-hub-signature-256 = sha256=hex
Dung saikhông quy định

Xác minh

Dùng raw body của request, đúng từng byte, trước mọi bước parse JSON. Mọi cơ chế trên trang này đều hỏng ngay khi framework serialize lại payload.

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);

Những chỗ dễ vấp

Bạn chỉ có đúng một lần gửi. Mọi bên gửi khác trong danh sách này đều tự thử lại; GitHub thì không, nên một lần deploy 30 giây cũng đủ làm rơi sự kiện mà không có cơ hội thứ hai. Nút Redeliver (và Redelivery API) chỉ gửi lại từng lượt gửi, bằng tay, trong 3 ngày. Sau đó chính bản ghi cũng không còn.

Đọc thêm

AnyHook đứng trước các endpoint nhận webhook từ GitHub: trả lời sau khoảng 1 giây, tự thử lại theo lịch riêng khi server của bạn ngừng hoạt động, và giữ mọi sự kiện để bạn phát lại được. Đổi một URL, giữ nguyên code.

Cách hoạt động →