-
Notifications
You must be signed in to change notification settings - Fork 27.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Presence of middleware prevents access to raw request bodies greater than or equal to 16,384 bytes (16 KiB) #39262
Comments
Sorry, I'm not necessarily here to answer your issue, but I did notice a potential bug when skimming through your code, export const config = {
api: {
bodyParser: {
bodyParser: false,
},
},
} According to these NextJS' guides, shouldn't this be: export const config = {
api: {
bodyParser: false,
},
} |
@Evilscaught good catch! (The perils of hacking away until well after midnight…) I’ve updated the code in the sample repo; this is what the corrected API page looks like:
import type { Readable } from 'node:stream';
import type { NextApiRequest, NextApiResponse } from 'next'
export const config = {
api: {
bodyParser: false,
},
}
async function buffer(readable: Readable) {
const chunks = [];
for await (const chunk of readable) {
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
}
return Buffer.concat(chunks);
}
export default async function (req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const buf = await buffer(req);
const rawBody = buf.toString('utf8');
// Can do something here...
res.json({ rawBody });
} else {
res.setHeader('Allow', 'POST');
res.status(405).end('Method Not Allowed');
}
} Fixing the Unfortunately, the issue as described originally is still present; any sort of middleware seems to prevent the processing of a raw body over 1-2kB. |
Same issue, post a multipart/form-data is prevented by middleware. When I remove middleware.ts file, it's work. |
After some additional digging, I’ve realized the I’ve reproduced the issue more precisely with a second test case at https://github.com/jhahn/nextjs-upload-issue/blob/main/pages/large-post.tsx: /** Add your relevant code here for the issue to reproduce */
export default function Home() {
const largePost = async () => {
const formData = new FormData()
const succeeds = new Uint8Array(16383);
const fails = new Uint8Array(16384);
self.crypto.getRandomValues(succeeds);
self.crypto.getRandomValues(fails);
const response = await fetch("/api/hello", {
method: "POST",
body: fails,
})
console.log(await response.json())
}
return <button onClick={largePost}>Send Large Post</button>
} A Adding a single byte (the (Again – when there’s no middleware, things work as they should) Fascinatingly, 16,384 bytes (16 KiB) corresponds exactly to the default |
I’ve updated the repo to |
I’ve updated the repo to |
I’ve updated the repo to |
Could the issue be related to this change? |
Apparently, it worked in I did some testing and while sending Example request: const response = await fetch("/api/hello", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({}),
}); EDIT: Looks like that small JSON payload issue was resolved by #35131, but the original issue still persists. Following up, in my testing the issue occurs regardless of |
🤖 I’ve updated the repo to |
@jhahn - I believe everyone following this issue appreciates you testing it with every release, thank you. It might be helpful to have a look at the canary release changelog to see whether there were any changes made to the related affected area. |
This problem appears on the 12.2.3 version. In the 12.2.2 there is no problem. |
Verified on my end and working when I changed the version to 12.2.2 Thank you @Pamboli ! |
Great find @Pamboli, looks like the issue was first introduced in |
I’ve updated the repo to the final release of I also did a bit of additional digging and confirmed the findings of @dmgawel:
If I had to hazard a guess, #34519 is the PR that introduced the issue. #34966 looks relevant, as does its fix #35131. |
Can you confirm this part ? Commenting away |
@sloonz good catch; thanks! While our use-case (uploaded files) requires access to the raw request body, I can confirm your findings that the issue occurs with or without the |
I have the same issue with |
Thanks for updating @jhahn ! Sadly downgrading did not help me, a bit unsure why but I will have to conduct further tests tomorrow. Removing the middleware worked great, but is necessary for the project I am working on so that is not an option. |
Actually, I just found and attempted with the matcher filter and I was able upload a 295Kb file without deleting the middleware on version 12.2.4! This is of course only an option if you can do without middleware on the paths you exclude.
A bit late so I will confirm further tomorrow. |
I’ve updated the sample repo to I can also confirm @Gawdfrey’s "matcher filter" workaround solves the issue, assuming you don’t need middleware on the excluded path(s). |
I’ve updated the sample repo to |
Thanks for the snippet works great for my use case! @ambrauer |
Same issue here. Only downgrading to 12.2.2 helps. After downgrading as well as applying
the API works as expected. |
Has anybody tested it with 12.3 yet? |
Just tested on 12.3 and have the same issue
|
@hoersamu @AndyChinViolet I can confirm that we are also having the same issue with 12.3.0. Downgrading to 12.2.0 works. |
Downgrading to 12.2.0 does not solve the problem for me while using withAuth from next-auth. |
It worked after downgrading to 12.2.2 and with next-auth default export in middleware and with matcher routes. |
I experienced the same issue. It took me a while to figure out, completely forgetting that middleware may be a factor. After downgrading from 12.3.0 to 12.2.2 I had no issues with uploads. |
I hope it'll be fixed soon... Downgrading to 12.2.2 also fixed the issue for me as well |
can confirm that downgrading to nextjs 12.2.2 (exact version, not ^12.2.2) fixes the issue for me as well |
Me too! 😅 Has anyone been able to identify the actual cause of the issue - in theory I'd be happy to raise a PR but don't currently have time to dig about trying to find the cause. |
@bcheidemann the issue was almost certainly (re)introduced in this PR: #38862 Because it contains a lot of changes regarding body streams and given I'm not familiar with Next.js internal code, I'm not able to point a single line or root cause. However, for Contributors it should be much easier to spot ;-) I hope pointing the PR helps. |
I proposed a solution (#41270). Any collaboration or suggestion is welcome. |
Fixes #39262 The solution is to call `stream.push(null)` to trigger the `end` event which allows `getRawBody` to run completely. <!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change that you're making: --> ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [x] Make sure the linting passes by running `pnpm lint` - [x] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <[email protected]>
…1270) Fixes vercel#39262 The solution is to call `stream.push(null)` to trigger the `end` event which allows `getRawBody` to run completely. <!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change that you're making: --> ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [ ] Errors have a helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have a helpful link attached, see `contributing.md` ## Documentation / Examples - [x] Make sure the linting passes by running `pnpm lint` - [x] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: JJ Kasper <[email protected]>
updating to version 13 solved the same issue I had. |
I solved this issue above [email protected] You can ignore middleware to specific routes through the Matcher
|
This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Verify canary release
Provide environment information
What browser are you using? (if relevant)
N/A
How are you deploying your application? (if relevant)
N/A
Describe the Bug
When attempting to upload a file over a few kilobytes (e.g. sending a
POST
request with a binary body and aContent-Type
ofmultipart/form-data
) viafetch
orcurl
, the request stalls, then fails with the error:This occurs only for API pages with…
…and only when middleware is present; even something as basic as:
Removing the middleware fixes the issue. Of note, very small request bodies (e.g. < 1kb files) work even in the presence of middleware.
Expected Behavior
Sending a POST request to an API endpoint with a Content-Type of
multipart/form-data
along with a reasonably sized (~200kB) binary payload should work and not stall.Link to reproduction
https://github.com/jhahn/nextjs-upload-issue
To Reproduce
pages/index.tsx
pages/api/hello.ts
:The code for
pages/api/hello.ts
was adapted from https://vercel.com/support/articles/how-do-i-get-the-raw-body-of-a-serverless-function. However, I had to changeconst buf = await buffer(req);
toconst buf = await buffer(req.body);
The text was updated successfully, but these errors were encountered: