Next.js集成Shopify Webhook遇stream is not readable错误求助
解决Next.js中Shopify GDPR Webhook验证的"stream is not readable"错误
我在开发Shopify应用时,需要添加GDPR Webhook,后端用Next.js实现,写了Webhook验证函数,但运行时抛出InternalServerError: stream is not readable错误。推测是Next.js提前解析了请求体,导致后续读取原始流时出错。原验证代码如下:
export function verifiedShopifyWebhookHandler( next: (req, res, body) => Promise ): NextApiHandler { return async (req, res) => { const hmacHeader = req.headers['x-shopify-hmac-sha256']; const rawBody = await getRawBody(req); const digest = crypto.createHmac('sha256', process.env.SHOPIFY_API_SECRET).update(rawBody).digest('base64'); if (digest === hmacHeader) { return next(req, res, rawBody); } const webhookId = req.headers['x-shopify-webhook-id']; return res.status(401).end(); }; }
解决思路及方案
- 禁用Next.js自动请求体解析
Next.js默认会自动解析JSON、URL编码表单等请求体,这会直接消耗请求流,导致后续无法读取原始内容。在你的API路由文件中添加config配置,关闭自动解析:
export const config = { api: { bodyParser: false, }, };
- 调整验证函数适配原始流
禁用自动解析后,req会是原始的IncomingMessage对象,此时可以正常用getRawBody读取。同时建议添加错误处理,避免流读取失败导致服务崩溃:
import crypto from 'crypto'; import getRawBody from 'raw-body'; import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'; export function verifiedShopifyWebhookHandler( next: (req: NextApiRequest, res: NextApiResponse, body: Buffer) => Promise<void> ): NextApiHandler { return async (req, res) => { try { const hmacHeader = req.headers['x-shopify-hmac-sha256'] as string; if (!hmacHeader) { return res.status(401).end('Missing HMAC header'); } const rawBody = await getRawBody(req, { length: req.headers['content-length'], limit: '1mb', // 根据Shopify Webhook的实际大小调整 }); const digest = crypto .createHmac('sha256', process.env.SHOPIFY_API_SECRET!) .update(rawBody) .digest('base64'); if (digest === hmacHeader) { // 如果后续业务需要JSON格式,可在此处解析原始内容 // const parsedBody = JSON.parse(rawBody.toString()); return next(req, res, rawBody); } return res.status(401).end('Invalid HMAC signature'); } catch (err) { console.error('Webhook verification failed:', err); return res.status(500).end('Internal server error'); } }; } // 路由配置必须添加 export const config = { api: { bodyParser: false, }, };
- 额外注意事项
- 确保
SHOPIFY_API_SECRET环境变量与Shopify后台配置的密钥完全一致 - Shopify Webhook默认发送
application/json格式,无需修改Content-Type,只需保证读取原始字节用于HMAC验证 - 测试时可使用Shopify官方的Webhook测试工具,或用curl构造原始请求验证逻辑
- 确保
内容的提问来源于stack exchange,提问作者BenMcL
相关产品推荐
相关产品推荐

