From ccaf00a8821b0ed50f6b963b8c340103dc58c447 Mon Sep 17 00:00:00 2001 From: nkzawa Date: Tue, 8 Mar 2022 16:13:13 +0700 Subject: [PATCH] fix post request hangs when no body is consumed on middleware --- packages/next/server/body-streams.ts | 8 ++++- packages/next/server/next-server.ts | 2 +- .../index.test.ts | 32 ++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/next/server/body-streams.ts b/packages/next/server/body-streams.ts index 5ce9a0b3abde..c4fc477d00b4 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 65876d9f2fdb..efe6800d06fc 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 0f1d61ccfa92..9e64502d8665 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') + }) })