diff --git a/packages/next/next-server/server/api-utils.ts b/packages/next/next-server/server/api-utils.ts index 33c6d45f4ce73d4..85d0156b97007fe 100644 --- a/packages/next/next-server/server/api-utils.ts +++ b/packages/next/next-server/server/api-utils.ts @@ -55,9 +55,17 @@ export async function apiResolver( apiRes.json = data => sendJson(apiRes, data) const resolver = interopDefault(resolverModule) + let wasPiped = false + + if (process.env.NODE_ENV !== 'production') { + // listen for pipe event and don't show resolve warning + res.once('pipe', () => (wasPiped = true)) + } + + // Call API route method await resolver(req, res) - if (process.env.NODE_ENV !== 'production' && !isResSent(res)) { + if (process.env.NODE_ENV !== 'production' && !isResSent(res) && !wasPiped) { console.warn( `API resolved without sending a response for ${req.url}, this may result in stalled requests.` ) diff --git a/test/integration/api-support/pages/api/test-res-pipe.js b/test/integration/api-support/pages/api/test-res-pipe.js new file mode 100644 index 000000000000000..c127f79c1fb9c32 --- /dev/null +++ b/test/integration/api-support/pages/api/test-res-pipe.js @@ -0,0 +1,10 @@ +import fetch from 'node-fetch' + +export default async (req, res) => { + const dataRes = await fetch( + `http://localhost:${req.query.port}/api/query?hello=from-pipe` + ) + + res.status(dataRes.status) + dataRes.body.pipe(res) +} diff --git a/test/integration/api-support/test/index.test.js b/test/integration/api-support/test/index.test.js index c66556733b2dbe7..c4e5c7d389b37a8 100644 --- a/test/integration/api-support/test/index.test.js +++ b/test/integration/api-support/test/index.test.js @@ -363,6 +363,14 @@ function runTests(dev = false) { `API resolved without sending a response for /api/test-no-end, this may result in stalled requests.` ) }) + + it('should not show warning when the API resolves and the response is piped', async () => { + const startIdx = stderr.length > 0 ? stderr.length - 1 : stderr.length + await fetchViaHTTP(appPort, `/api/test-res-pipe`, { port: appPort }) + expect(stderr.substr(startIdx)).not.toContain( + `API resolved without sending a response for /api/test-res-pipe` + ) + }) } else { it('should build api routes', async () => { const pagesManifest = JSON.parse(