`bodyUsed` and `response.clone()` not working as expected
FGoessler opened this issue · 1 comments
Describe the bug
A response body - as it is based on streams/buffers - can only be used once.
bodyUsed
should return false once a body has been used.
Calling .clone()
on a response should effectively clone the response, enabling a repeat consumption of the body.
Source: MDN Docs here and here.
Both is not the case for the fetch/response implementation in this repository.
To Reproduce
Setup a simple node.js project with dependencies for node-fetch
and @whatwg-node/fetch
to compare results.
package.json
:
...
"dependencies": {
"@whatwg-node/fetch": "^0.9.16",
"node-fetch": "^3.3.2"
},
...
main.mjs
:
import { fetch as whatwgFetch } from '@whatwg-node/fetch'
import fetch from 'node-fetch'
async function test(fetchFunc) {
const res = await fetchFunc('https://example.com')
const res2 = res.clone()
console.log("first res bodyUsed before: " + res.bodyUsed)
console.log("first res: " + (await res.text()).length)
console.log("first res bodyUsed after: " + res.bodyUsed)
console.log("second res: " + (await res2.text()).length)
}
// use with whatwg-fetch:
test(whatwgFetch).then(() => console.log('done')).catch(e => console.error(e))
// Prints:
// first res bodyUsed before: false ─╯
// first res: 1256
// first res bodyUsed after: false
// or use with node-fetch:
// test(fetch).then(() => console.log('done')).catch(e => console.error(e))
// Prints:
// first res bodyUsed before: false ─╯
// first res: 1256
// first res bodyUsed after: true
// second res: 1256
// done
- As you can see the
bodyUsed
flag gives no indication that the body has been used. - For the consumption of the cloned response no data is available.
- Note how no
done
is printed because the promise actually hangs indefinitely, trying to create a buffer or so.
Expected behavior
- Once a response's body is used the
response.bodyUsed
returnstrue
. - Calling
réponse.clone()
creates a proper clone of the response that enables rereading the response body on the copy. - Trying to reread an already consumed body causes a
TypeError: body used already for: <url>
.
Environment:
- OS:
macOS 13.2
"@whatwg-node/fetch": "^0.9.16"
- NodeJS:
v20.11.0
andv18.19.0
Additional context
Found during debugging ardatan/graphql-mesh#6593 . Proper response body consumption guards would have helped finding the source of that issue as the system would blow up properly with a TypeError: body used already for: <url>
and not run into a hanging promise.