FileStreamDisconnectUploadError when checking file validity
See original GitHub issueHello,
The problem
I have a problem when checking for the validity of the files sent by multipart request from the client side.
The client sends a multipart request with maximum 5 different files, then the server loops through them to check if every file is an instance of stream.Readable
. While looping through the files an error occures: FileStreamDisconnectUploadError: Request disconnected during file upload stream parsing.
.
The first file is checked but then the others files are never read.
This is what my loop looks like:
for (const pic of data.pictures) {
const resolved = await pic;
if (!(resolved.stream instanceof stream.Readable)) return new Error('Wrong file');
}
The error is raised when executing the line const resolved = await pic;
.
The first file fills the resolved
variable but it never gets filled again with the next files.
What I tried
- I tried to destroy the stream after the check:
resolved.stream.destroy();
- I tried to replace the
for...of
loop with amap
Some thoughts
Before making the requests by the client, I sent the requests using curl according to these examples. But the error still occured.
I work on a Macbook with MacOS Sierra 10.12.6 and curl 7.54.0 which uses SecureTransport
, as it is the native TLS library.
What is interesting is that my coworkers, which work with the same Macbook as mine but with MacOS High Sierra and curl 7.54.0 which uses LibreSSL
as TLS library, manage to get the requests work with the server. Of course we tried with the exact same requests and on a server running on my mac.
Do you have any idea why the error occures and why does the await pic
never manage to complete ?
Thanks for your time.
Issue Analytics
- State:
- Created 5 years ago
- Comments:38 (8 by maintainers)
Apologies for my unconstructive tone.
I finally see what you mean now. The query example explains it all.
Again, I realised that talking about code but not seeing the code often leads to an unconstructive discussion.
PS: I’ve refactored the code back to it’s original state little above in this thread: https://github.com/jaydenseric/graphql-upload/issues/65#issuecomment-382922064
You may want to reread my post… my “less ideal” scenario has nothing to do with dependancies of files on each other, or other data. Instead, it has to do with the HTTP request, which is a linear stream of bytes that can contain uploads in a different order than you expect in your resolver. Consider this example query:
This kind of request is valid GraphQL and must still be valid when using the the upload spec to do variable replacement. Therefore, the upload spec cannot constrain the order of uploads in the HTTP request such that it matches the order of appearance in every list.
It is completely possible that your upload stream will contain the contents of
$uploadC
first, followed by$uploadB
, then$uploadA
. You don’t get to decide this, because you aren’t sending the request; the client is. If your code is waiting on$uploadA
before processing$uploadB
, then it is inefficient.Also, there are scenarios where business logic requires one upload to be present before another becomes useful; just because you haven’t run into one doesn’t mean they don’t exist. Your tone here is painfully hyperbolic and very much in contrast to the meticulous attention to edge cases that has made this library suitable for such a wide range of use cases. If you have good feedback, we want to hear it, and dismissive hand-waving is counterproductive to meaningful communication of an intricate subject.
That’s not how promises work. Promises are executed eagerly, meaning that they run as soon as they are created. Something like
Promise.all
does not cause them to run but instead “pauses” the current flow when usingawait
(or waits to call any functions registered with.then()
) until all its promises (which are already running) resolve.I suspect your example does not work the way you think it works, and if it does, I don’t believe it represents a common use case. In my experience, it’s been standard practice to ensure the file is stored without error before returning a “successful” response.
Keeping in mind that the HTTP response won’t make it to the browser until the request has finished, your resolver should almost certainly be refactored to: