Cannot calculate proper length in synchronous way. (node-fetch + form-data)
mahnunchik opened this issue · 16 comments
Error: Cannot calculate proper length in synchronous way.
at FormData.getLengthSync (node_modules/form-data/lib/form_data.js:245:17)
at node_modules/node-fetch/index.js:96:48
at new Fetch (node_modules/node-fetch/index.js:49:9)
at Fetch (node_modules/node-fetch/index.js:37:10)
This line causes the error: https://github.com/bitinn/node-fetch/blob/master/index.js#L96
This is a hack to support form-data
module, so you don't have to set content-length
header manually. You might want to figure out why form-data
throws this error in the first place (probably related to your body data type).
I've tried to send following body:
form.append('my_file', fs.createReadStream('/foo/bar.jpg'));
Due to the nature of callback, we don't currently use getLength
to determine form-data
's content-length
, but you can calculate the content-length
yourself (either with FormData.getLength
or count the stream byte itself) then pass it onto node-fetch
's headers
option manually, this will skip the hack as content-length
is provided already.
I have worked around this bug for the moment by removing the getLengthSync
method before passing it to node-fetch
form.getLengthSync = null;
Some servers don't like it not having a content-length
header, but its certainly not required by the spec and many servers will work fine without it.
@mcfedr please don't do this, why can't you call getLength
to figure out content-length
?
UPDATE: see my reply here #106 (comment)
Alternative, don't use form-data
, because you are just sending files right? Only use form-data
to manage your custom headers, let node-fetch
handle the body as native stream instead of form-data
instance.
For local files its possible to use fs.stat
and set knownLength
when adding to form-data
I am sending another stream, and I dont know the length of the stream. Here are example of how things are broken, these are bugs in both node-fetch
and form-data
https://gist.github.com/mcfedr/0a6fbaeaf0cfaddbeadfe145c002c8e5
I think in the 'http' example node-fetch should ignore the correctly thrown error and be ok with not setting a content-length
In the 'fetch' example form-data needs to throw the error because it doesnt know its length
Quick summary: unfortunately form-data
doesn't have an API for checking whether we can call getLengthSync
yet, so we have 3 options:
- to do it correctly and manually, end user can do the calculation with
form.getLength
callback and overwrite our default behavior with customcontent-length
- to not add content-length at all, use the
form.getLengthSync = null
hack mcfedr mentioned to preventnode-fetch
from callinggetLengthSync
- we might add a
formdata._lengthRetrievers.length > 0
check to skip callinggetLengthSync
automagically, as discussed in form-data/form-data#196
No response from form-data dev, I am going with option 3.
@havenchyk I will update this issue when release, but you should read my reply above #102 (comment)
@bitinn thanks for the quick response. I actually read it and understand that I need to skip the check somehow.
My problem is that everything worked fine for a year and now it's broken. I'm trying to figure out, is it a problem of FormData(maybe from last releases) or of node-fetch.
@havenchyk my work around works, #102 (comment)
@havenchyk I need to see the error to conclusively say you are facing the same problem. But form-data
has been doing this for quite some time, so unless you changed your data source to a stream, I don't see why it would suddenly break (unless you upgrade from a very old node-fetch
which doesn't use hack to handle form-data
previously)
workaround has been added and released as v1.5.3