सभी लेख
Next.jsApp Routerwebhook debugginglocal testing

localhost पर Next.js वेबहुक, सही तरीके से

Next.js App Router में टूटे वेबहुक handler का सबसे बड़ा स्रोत कच्चा body है। App Router ठीक है। route handler ठीक हैं। पर अनपार्स्ड request body पकड़ने के तरीके Pages Router और App Router के बीच बदल गए, और अधिकांश Stripe / GitHub / Shopify इंटीग्रेशन पुरानी दुनिया से snippet कॉपी करते हैं। यह लेख नई दुनिया है।

दो-पंक्ति नियम

App Router route handler में कच्चा body await request.text() से लें। सिग्नेचर सत्यापन से पहले request.json() उपयोग न करें। Pages Router की तरह bodyParser अक्षम करने की कोशिश न करें — वह flag अब मौजूद नहीं।

// app/api/webhooks/stripe/route.ts
import Stripe from 'stripe';
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(request: Request) {
  const body = await request.text();   // raw, not parsed
  const signature = (await headers()).get('stripe-signature')!;

  let event;
  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      process.env.STRIPE_WEBHOOK_SECRET!,
    );
  } catch (err) {
    return NextResponse.json(
      { error: 'invalid signature' },
      { status: 400 },
    );
  }

  // Handle the event
  switch (event.type) {
    case 'checkout.session.completed':
      // ...
      break;
  }

  return NextResponse.json({ received: true });
}

तीन पंक्तियाँ ध्यान देने योग्य: request.text() वह कच्ची स्ट्रिंग देता है जिसे Stripe ने साइन किया। App Router में headers() async है — await पर ध्यान दें। और सिग्नेचर सत्यापन किसी भी JSON.parse समकक्ष से पहले होना चाहिए।

भूलने योग्य Pages Router की आदत

यदि आप Pages Router से माइग्रेट हुए हैं, आपको यह लिखना याद होगा:

// pages/api/webhooks/stripe.ts (OLD)
export const config = { api: { bodyParser: false } };

वह config App Router में मौजूद नहीं। body Request ऑब्जेक्ट से माँग पर पढ़ा जाता है। जो आप दूसरा पढ़ते हैं वह खाली है — request.json() के बाद request.text() कुछ नहीं लौटाता। एक चुनें, और वेबहुक के लिए हमेशा text() चुनें।

Next.js dev के लिए टनल सेटअप

  1. next dev (या npm run dev) चलाएँ — आमतौर पर पोर्ट 3000।
  2. दूसरे टर्मिनल में npx portpreview 3000
  3. HTTPS URL अपने प्रदाता की वेबहुक कॉन्फ़िगरेशन में पेस्ट करें। Stripe के लिए: Developers → Webhooks → Add endpoint
  4. एक टेस्ट इवेंट ट्रिगर करें। अनुरोध सभी हेडर बरकरार के साथ आपके route handler पर आता है।

यदि next dev --turbo उपयोग करते हैं, यह फिर भी काम करता है। Turbopack bundler बदलता है, request/response मॉडल नहीं।

Edge runtime: मत करें

यदि आपने वेबहुक route handler पर export const runtime = 'edge' सेट किया है, आप Node-केवल crypto API तक पहुँच खो देंगे जिन्हें कुछ प्रदाता SDK उपयोग करते हैं। Stripe Node SDK हाल के संस्करणों में edge पर काम करता है, पर मनमाने प्रदाताओं के साथ सिग्नेचर सत्यापन अनिश्चित है। विशिष्ट कारण न हो तो वेबहुक रूट Node runtime पर रखें।

export const runtime = 'nodejs'; // explicit, safe default for webhooks

App Router के जाल जिनमें हम बार-बार फँसते हैं

गलत प्रकार लौटाना

यदि आप NextResponse.json(...) के बजाय new Response(JSON.stringify(...)) लौटाते हैं, content-type हेडर सेट न हो सकता है। कुछ प्रदाता परवाह करते हैं। NextResponse.json() उपयोग करें या हेडर मैन्युअल सेट करें।

स्ट्रीमिंग और websocket

वेबहुक handler अल्पकालिक HTTP अनुरोध हैं, पर यदि आप ऐसी Next.js ऐप टनल करते हैं जिसमें WebSocket रूट भी हैं (उदाहरण के लिए कस्टम सर्वर पर socket.io), सुनिश्चित करें कि आपका टनल WebSocket upgrade संरक्षित करता है। अधिकांश करते हैं; दस्तावेज़ देखें।

body पढ़ने वाला middleware

यदि जड़ पर एक middleware.ts है जो लॉगिंग या auth के लिए request.text() कॉल करता है, आपका वेबहुक रूट body कभी नहीं देखता। अपने matcher में वेबहुक पथ छोड़ें या केवल उन रूट में body पढ़ें जिन्हें ज़रूरत है।

Vercel डिप्लॉय आपको नहीं बचाएँगे

कच्चे body पार्सिंग पर निर्भर वेबहुक बग Vercel और localhost पर समान व्यवहार करते हैं। जब आपका लोकल टनल टेस्ट सिग्नेचर सत्यापन पास करता है, डिप्लॉय किया संस्करण भी करेगा — जब तक आप serverless तरफ मेमोरी या timeout सीमा से न टकराएँ, जिस स्थिति में लक्षण अलग है (5xx, 401 नहीं)।

Stripe विशिष्टताओं के लिए Stripe वेबहुक लोकल टेस्टिंग गाइड देखें। सामान्य रूप से सिग्नेचर गणित के लिए सिग्नेचर सत्यापन गाइड। capture के साथ Next.js-अनुकूल टनल पाने के लिए PortPreview वेटलिस्ट में शामिल हों

अक्सर पूछे जाने वाले प्रश्न

Next.js App Router वेबहुक में कच्चा body कैसे प्राप्त करूँ?
POST handler के भीतर await request.text() कॉल करें। पहले request.json() कॉल न करें — एक बार body पढ़ा जाने पर, .text() या .json() की दूसरी कॉल कुछ नहीं लौटाती।
क्या मुझे Next.js App Router में bodyParser: false चाहिए?
नहीं। वह config Pages Router का पैटर्न था और App Router में इसका कोई समकक्ष नहीं। body Request ऑब्जेक्ट से माँग पर पढ़ा जाता है, और जब भी आपको सिग्नेचर सत्यापित करना हो आप इसे कच्चे text के रूप में पढ़ते हैं।
क्या मैं Next.js edge runtime पर वेबहुक रूट चला सकता हूँ?
चला सकते हैं, पर सिग्नेचर सत्यापन SDK कभी-कभी Node crypto API पर निर्भर होते हैं जो edge पर उपलब्ध नहीं। स्विच करने का विशिष्ट कारण न हो तो वेबहुक के लिए डिफ़ॉल्ट Node runtime पर रहें।