Octokit Webhooks集成Express服务器失效问题求助
问题解决:Octokit Webhook在Express中无法触发事件(返回202状态码)
问题原因
你在Express中提前全局使用了express.json()中间件,它会先解析请求体并消耗请求流。而Octokit的Webhook中间件需要读取原始未解析的请求体来验证GitHub的签名,请求流被消耗后,中间件无法获取正确的原始数据,导致签名验证失败,因此返回202状态码且不触发事件。
解决方案
移除全局的express.json()中间件,或者仅在非Webhook路径上使用该中间件,让Octokit的中间件直接处理Webhook路径的原始请求:
修改后的Express代码
import express, { Request, Response } from "express"; import dotenv from "dotenv"; import { createNodeMiddleware } from "@octokit/webhooks"; import fs from "fs"; import { App } from "@octokit/app"; dotenv.config(); const PORT = process.env.PORT || 8000; const expressApp = express(); const appId = process.env.APP_ID ?? ""; const webhookSecret = process.env.WEBHOOK_SECRET ?? ""; const privateKeyPath = process.env.PRIVATE_KEY_PATH ?? ""; const privateKey = fs.readFileSync(privateKeyPath, "utf8"); const octokitApp = new App({ appId, privateKey, webhooks: { secret: webhookSecret }, }); // 仅对非Webhook路径使用JSON解析中间件 expressApp.use((req, res, next) => { if (req.path !== "/api/webhook") { express.json()(req, res, next); } else { next(); } }); const middleware = createNodeMiddleware(octokitApp.webhooks, { path: "/api/webhook", }); expressApp.use(middleware); octokitApp.webhooks.onAny(() => { console.log(`Webhook event received`); }); octokitApp.webhooks.on("pull_request.reopened", () => console.log(`Pull request reopened event triggered`)); expressApp.get("/", (req: Request, res: Response) => { return res.status(200).json({ message: "Hello world", }); }); expressApp.listen(PORT, () => console.log(`Server is running at port ${PORT}`));
关键说明
- GitHub Webhook的签名验证依赖原始请求体的字节内容,任何提前解析请求体的操作都会破坏验证流程。
- Octokit的
createNodeMiddleware内部已经处理了请求体的解析,无需手动给Webhook路径添加express.json()。 - 202状态码是Octokit在签名验证失败时返回的默认状态,表示请求已接受但未处理。
内容的提问来源于stack exchange,提问作者Jashandeep Singh
相关产品推荐
相关产品推荐

