diff --git a/packages/next/server/body-streams.ts b/packages/next/server/body-streams.ts index 5ce9a0b3abde2..c4fc477d00b4e 100644 --- a/packages/next/server/body-streams.ts +++ b/packages/next/server/body-streams.ts @@ -58,14 +58,20 @@ export function clonableBodyForRequest( ) { let bufferedBodyStream: BodyStream | null = null + const endPromise = new Promise((resolve, reject) => { + incomingMessage.on('end', resolve) + incomingMessage.on('error', reject) + }) + return { /** * Replaces the original request body if necessary. * This is done because once we read the body from the original request, * we can't read it again. */ - finalize(): void { + async finalize(): Promise { if (bufferedBodyStream) { + await endPromise replaceRequestBody( incomingMessage, bodyStreamToNodeStream(bufferedBodyStream) diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index 65876d9f2fdb7..efe6800d06fc4 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -1314,7 +1314,7 @@ export default class NextNodeServer extends BaseServer { } } - originalBody?.finalize() + await originalBody?.finalize() return result } diff --git a/test/production/reading-request-body-in-middleware/index.test.ts b/test/production/reading-request-body-in-middleware/index.test.ts index 0f1d61ccfa92e..9e64502d86656 100644 --- a/test/production/reading-request-body-in-middleware/index.test.ts +++ b/test/production/reading-request-body-in-middleware/index.test.ts @@ -16,7 +16,11 @@ describe('reading request body in middleware', () => { return new Response('No body', { status: 400 }); } - const json = await request.json(); + let json; + + if (!request.nextUrl.searchParams.has("no_reading")) { + json = await request.json(); + } if (request.nextUrl.searchParams.has("next")) { const res = NextResponse.next(); @@ -141,4 +145,30 @@ describe('reading request body in middleware', () => { }) expect(response.headers.get('x-from-root-middleware')).toEqual('1') }) + + it('passes the body to the api endpoint when no body is consumed on middleware', async () => { + const response = await fetchViaHTTP( + next.url, + '/api/hi', + { + next: '1', + no_reading: '1', + }, + { + method: 'POST', + headers: { + 'content-type': 'application/json', + }, + body: JSON.stringify({ + foo: 'bar', + }), + } + ) + expect(response.status).toEqual(200) + expect(await response.json()).toEqual({ + foo: 'bar', + api: true, + }) + expect(response.headers.get('x-from-root-middleware')).toEqual('1') + }) })