Reputation: 665
I was trying to send a post request to my api. However trying to access the request body in the route handler causes the error below:
Code:
export async function POST(request: Request) {
const postBody: postProps = JSON.parse(request.body) // 👈 Error here on request.body
...
}
Error: Argument of type 'ReadableStream' is not assignable to parameter of type 'string'.
Any help would be appreciated
Upvotes: 30
Views: 38168
Reputation: 391
After battling with this issue for an hour, I had to comment output
prop in next.config.js
to get request.json() to deliver the request's body.
const nextConfig = {
// "output": "export",
"distDir": "build",
experimental: {
serverActions: true
}
}
I'm still trying to understand the connection. Shouldn't I be able to build my client components to a dir?
Upvotes: 1
Reputation: 31
I was having trouble getting a Stripe webhook to work using App Router. The following worked for me (using Kyle's method of getting the raw body).
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-08-16',
});
import { NextRequest, NextResponse } from 'next/server';
const WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET;
export async function POST(req: NextRequest) {
const rawBody = await req.text(); // gets the raw body from the request
const sig = req.headers.get('stripe-signature');
let event;
let result = 'Webhook called.';
try {
event = stripe.webhooks.constructEvent(rawBody, sig!, WEBHOOK_SECRET!);
} catch (err: any) {
console.error(err);
return NextResponse.json({ error: err.message }, { status: 400 });
}
// Handle the event
switch (event.type) {
case 'payment_intent.created':
console.log('Payment Intent Created.');
break;
case 'payment_intent.payment_failed':
console.log('Payment Failed.');
break;
case 'payment_intent.processing':
console.log('Payment processing...');
break;
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('paymentIntent: ', paymentIntent);
console.log(`Payment Succeeded`);
break;
// ... handle other event types
default:
console.warn(`Unhandled event type ${event.type}`);
}
return NextResponse.json({ received: true, status: result });
}
Also, you cannot call both req.json() and req.text(). You will get a body consumed error.
Upvotes: 3
Reputation: 106
I was having issues Verifying the webhook from Clerk in Next.js using App Router.
The following worked for me.
import { Webhook } from "svix";
export async function POST(req: NextRequest) {
const svix_id = req.headers.get("svix-id") ?? '';
const svix_timestamp = req.headers.get("svix-timestamp") ?? '';
const svix_signature = req.headers.get("svix-signature") ?? '';
const body = await req.text(); // This get's the raw body as a string
const sivx = new Webhook("your_secret_key_here")
const payload = sivx.verify(body, {
"svix-id": svix_id,
"svix-timestamp": svix_timestamp,
"svix-signature": svix_signature,
});
// The payload is the json.
console.log(payload);
// The rest of your code
return NextResponse.json(null, { status: 200 })
}
For reference:
https://developer.mozilla.org/en-US/docs/Web/API/Response/text
Upvotes: 6