Closed pi0 closed 3 weeks ago
This also occurs on Netlify:
export default defineEventHandler(async event => {
if (event.method !== "POST") {
throw createError({statusCode:405, statusMessage: 'Method not allowed'});
}
let form: FormData;
try {
console.log('readFormData::enter');
form = await readFormData(event);
console.log('readFormData::exit');
} catch (cause) {
console.log('readFormData::error');
throw createError({
statusCode: 400,
statusMessage: 'Request has no FormData',
cause,
});
}
return form;
});
Output (via Logs > Functions on Netlify's admin panel)
Nov 20, 02:46:34 PM: INIT_START Runtime Version: nodejs:18.v18 Runtime Version ARN: arn:aws:lambda:us-east-2::runtime:(snip)
Nov 20, 02:46:34 PM: (snip) INFO readFormData::enter
Nov 20, 02:46:34 PM: (snip) Duration: 39.99 ms Memory Usage: 78 MB Init Duration: 215.70 ms
The result is a 502 with message:
error decoding lambda response: invalid status code returned from lambda: 0
There are two major issues here:
With this severity of a crash, I'd honestly prefer the readFormData
function be replaced with an always throwing function. That would not change the absence of it's functionality and you would gain back the ability to recover from the failure.
Also, the developer(s) do not need to go around in circles trying out different small changes to their code to hunt this bug down.
Using console.log(event)
, the event.node.req.body
property holds the actual body of the request already.
Reviewing the code for h3, specifically src/utils/body.ts
, it seems there are wildly different ways of parsing the request. I wouldn't be surprised if some of the functions there would actually be able to parse the request properly.
For example, readRawBody
does reach for the event.node.req.body
property. While the readFormData
does not.
I'll see if I can find a variant that works on netlify and then the toWebRequest
or readFormData
may be modified to use that approach as well.
This is a fixed version of readFormData
that will work on netlify, and perhaps also vercel (given that it is also AWS based):
async function readFormData_fixed(event: H3Event) : Promise<FormData> {
const request = new Request(getRequestURL(event), {
// @ts-ignore Undici option
duplex: 'half',
method: event.method,
headers: event.headers,
body: await readRawBody(event),
} as RequestInit);
return await request.formData();
}
I ran into a similar problem with Netlify: https://github.com/unjs/h3/issues/590
Having this problem in solid start as well. Appears on cloudflare workers, netlify edge and vercel edge
Hi,
I have been having the same issue in solid start on the cloudflare env.
Accessing the event.web.request
or event._requestBody
it can't be read. Instead wrangler is generating an error stating A hanging Promise was canceled.
The only request object that can be used is the event.node.req.body
.
@AirBorne04 sadly we don't officially support Solid as they diverged. Sorry for you hearing this. I advice you to seek support in their channel.
no problem @pi0 the PR for fixing it on the Solid side is already merged.
This issue is already fixed with https://github.com/unjs/h3/pull/616 (h3@1.10.1)
I have implemented an end-to-end test which passes on edge platforms:
Note: Tests are against unmodified Nitro behavior.
Moving from https://github.com/unjs/nitro/discussions/1718 reported by @cosbgn
Minimal reproduction:
routes/index.ts:
(checking console, response never handles)
Workaround
You can use the older
readMultipartFormData
utility. It returns an array of form datas:https://nitro-ppspi2qf2-pi0.vercel.app/