Skip to content

Commit 62f948d

Browse files
Merge branch 'canary' into fix/api-error-bubbling
2 parents 8f340b4 + 3b592e2 commit 62f948d

File tree

7 files changed

+63
-1
lines changed

7 files changed

+63
-1
lines changed

errors/api-routes-body-size-limit.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# API Routes Body Size Limited to 5mb
2+
3+
#### Why This Error Occurred
4+
5+
API Routes are meant to respond quickly and are not intended to support responding with large amounts of data. The maximum size of responses is 5 MB.
6+
7+
#### Possible Ways to Fix It
8+
9+
Limit your API Route responses to less than 5 MB. If you need to support sending large files to the client, you should consider using a dedicated media host for those assets. See link below for suggestions.
10+
11+
### Useful Links
12+
13+
[Tips to avoid the 5 MB limit](https://vercel.com/support/articles/how-to-bypass-vercel-5mb-body-size-limit-serverless-functions)

errors/manifest.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
"title": "amp-export-validation",
1414
"path": "/errors/amp-export-validation.md"
1515
},
16+
{
17+
"title": "api-routes-body-size-limit",
18+
"path": "/errors/api-routes-body-size-limit.md"
19+
},
1620
{
1721
"title": "api-routes-static-export",
1822
"path": "/errors/api-routes-static-export.md"

packages/next/pages/_document.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,12 @@ function getPreNextScripts(context: DocumentProps, props: OriginProps) {
7676
const { scriptLoader, disableOptimizedLoading } = context
7777

7878
return (scriptLoader.beforeInteractive || []).map(
79-
(file: ScriptLoaderProps) => {
79+
(file: ScriptLoaderProps, index: number) => {
8080
const { strategy, ...scriptProps } = file
8181
return (
8282
<script
8383
{...scriptProps}
84+
key={scriptProps.src || index}
8485
defer={!disableOptimizedLoading}
8586
nonce={props.nonce}
8687
crossOrigin={props.crossOrigin || process.env.__NEXT_CROSS_ORIGIN}

packages/next/server/api-utils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ export async function apiResolver(
6363
)
6464
}
6565

66+
let contentLength = 0
67+
const writeData = apiRes.write
68+
const endResponse = apiRes.end
69+
apiRes.write = (...args: any[2]) => {
70+
contentLength += Buffer.byteLength(args[0])
71+
return writeData.apply(apiRes, args)
72+
}
73+
apiRes.end = (...args: any[2]) => {
74+
if (args.length && typeof args[0] !== 'function') {
75+
contentLength += Buffer.byteLength(args[0])
76+
}
77+
78+
if (contentLength >= 5 * 1024 * 1024) {
79+
console.warn(
80+
`API response for ${req.url} exceeds 5MB. This will cause the request to fail in a future version. https://nextjs.org/docs/messages/api-routes-body-size-limit`
81+
)
82+
}
83+
84+
endResponse.apply(apiRes, args)
85+
}
6686
apiRes.status = (statusCode) => sendStatusCode(apiRes, statusCode)
6787
apiRes.send = (data) => sendData(apiReq, apiRes, data)
6888
apiRes.json = (data) => sendJson(apiRes, data)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default (req, res) => {
2+
for (let i = 0; i <= 5 * 1024 * 1024; i++) {
3+
res.write('.')
4+
}
5+
res.end()
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default (req, res) => {
2+
let body = '.'.repeat(5 * 1024 * 1024)
3+
res.send(body)
4+
}

test/integration/api-support/test/index.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,20 @@ function runTests(dev = false) {
398398
expect(data).toBe('hi')
399399
})
400400

401+
it('should warn if response body is larger than 5MB', async () => {
402+
let res = await fetchViaHTTP(appPort, '/api/large-response')
403+
expect(res.ok).toBeTruthy()
404+
expect(stderr).toContain(
405+
'API response for /api/large-response exceeds 5MB. This will cause the request to fail in a future version.'
406+
)
407+
408+
res = await fetchViaHTTP(appPort, '/api/large-chunked-response')
409+
expect(res.ok).toBeTruthy()
410+
expect(stderr).toContain(
411+
'API response for /api/large-chunked-response exceeds 5MB. This will cause the request to fail in a future version.'
412+
)
413+
})
414+
401415
if (dev) {
402416
it('should compile only server code in development', async () => {
403417
await fetchViaHTTP(appPort, '/api/users')

0 commit comments

Comments
 (0)