undici
undici copied to clipboard
Using a global FormData with undici.request causes a TypeError
Bug Description
Using a global FormData with undici.request causes a TypeError: Cannot read properties of null (reading 'byteLength')
"I found that this is the case because util.isFormDataLike() is true here https://github.com/nodejs/undici/blob/2ed2a8a1393b0da3215997e9941ec3a92a93f3d0/lib/dispatcher/client-h1.js#L1021 but webidl.is.FormData is false here https://github.com/nodejs/undici/blob/2ed2a8a1393b0da3215997e9941ec3a92a93f3d0/lib/web/fetch/body.js#L120"
Reproducible By
import { request, setGlobalDispatcher, Agent } from './index.js'
import { createServer } from 'node:http'
import { once } from 'node:events'
setGlobalDispatcher(new Agent())
const server = createServer((req, res) => {
req.pipe(res).on('end', () => res.end())
}).listen(0)
await once(server, 'listening')
const fd = new FormData()
fd.set('a', 'b')
await request(`http://localhost:${server.address().port}`, {
method: 'POST',
body: fd
}).finally(() => server.close())
Expected Behavior
Logs & Screenshots
Environment
Additional context
This patch seems to fix this:
diff --git a/lib/web/fetch/body.js b/lib/web/fetch/body.js
index 81d9b6d0e67a11ecb51241e0daf3b8a05cd11b49..d5edc13e5f2216ab47d21291ed8aca22f52b7191 100644
--- a/lib/web/fetch/body.js
+++ b/lib/web/fetch/body.js
@@ -117,7 +117,7 @@ function extractBody (object, keepalive = false) {
// Set source to a copy of the bytes held by object.
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength))
- } else if (webidl.is.FormData(object)) {
+ } else if (util.isFormDataLike(object)) {
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}`
const prefix = `--${boundary}\r\nContent-Disposition: form-data`
Seeing the same issue with FormData imported from undici
Hi, struggling to find what resolved this, can you enlighten me please? A quick check reveals I can still reproduce this with 4608ef157cc75d5ce3d2802e6949cb865d73146c.
I don't view this as a bug. At most, the error could be improved.
I don't understand what's the workaround?
Can you elaborate why you think not being able to pass global FormData in NodeJS to undici methods is not a bug, considering the native fetch() function in NodeJS is undici and accepts it just fine?
I don't understand what's the workaround?
There are a few, but one for library authors:
import { FormData as UndiciFormData, request } from 'undici'
function globalToUndiciFormData(fd: globalThis.FormData): UndiciFormData {
const clone = new UndiciFormData()
for (const [name, value] of fd.entries()) {
if (typeof value === 'string') {
clone.append(name, value)
} else {
clone.append(name, value, value.name) // I don't know if this is needed
}
}
return clone
}
const fd = new FormData()
fd.set('a', new Blob(['...']), 'blob.txt')
await request('https://a', {
method: 'POST',
body: globalToUndiciFormData(fd)
})
Can you elaborate why you think not being able to pass global FormData in NodeJS to undici methods is not a bug
https://github.com/nodejs/undici/issues/2674 https://github.com/nodejs/undici/issues/3896
the native fetch in node is a version of undici that is not necessarily compatible with an up-to-date (or outdated) version.
, considering the native fetch() function in NodeJS is undici and accepts it just fine?
This would be a bug, or it's what I am talking about above.