router
router copied to clipboard
Upload file mutation failed
Describe the bug I try to upload files via graphql
curl -v localhost:4000/ \
-F operations='{ "query": "mutation ($file: Upload!) { singleUpload(file: $file) { location } }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@/File/location/to/add.jpg
and get this response
* Trying ::1:4000...
* connect to ::1 port 4000 failed: Connection refused
* Trying 127.0.0.1:4000...
* Connected to localhost (127.0.0.1) port 4000 (#0)
> POST / HTTP/1.1
> Host: localhost:4000
> User-Agent: curl/7.77.0
> Accept: */*
> Content-Length: 1269305
> Content-Type: multipart/form-data; boundary=------------------------f6d06ed6d2fc8b81
> Expect: 100-continue
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 415 Unsupported Media Type
< content-type: text/plain; charset=utf-8
< content-length: 43
< date: Wed, 13 Apr 2022 06:15:28 GMT
* HTTP error before end of send, stop sending
<
* Closing connection 0
The request's content-type is not supported
is there any way to add configuration/plugin in apollo router to support feature upload?
Expected behavior
The request Upload (Content-type=multipart/form-data
) should be accepted by the Router and forwarding the request to the subgraph.
reference: https://github.com/jaydenseric/graphql-multipart-request-spec
this is not possible in the router right now, and would require significant changes. Do you currently have a gateway that supports it? I'm asking about the gateway because the expected behaviour might not be obvious. Would the router buffer the entire file before sending to the subgraph? Or the subgraph supports multipart upload too and data is streamed?
@Geal
Do you currently have a gateway that supports it?
I used https://github.com/nautilus/gateway for gateway before, and this library supports multipart upload.
the subgraph supports multipart upload too and data is streamed?
and the subgraph for upload, I used https://gqlgen.com/reference/file-upload/
Would the router buffer the entire file before sending it to the subgraph?
If I'm not mistaken, they kept the entire files on the gateway and then sent them to the subgraph.
You can see it on this repository https://github.com/nautilus/graphql/blob/master/queryerNetwork.go#L60-L67 on how they process the upload file to the subgraph.
this is not possible in the router right now, and would require significant changes
@Geal I'm encountering the same thing while trying to adopt Apollo Router with gqlgen for the subgraph. I would prefer to send the file upload operation through the router so all plugins are shared for the request.
The multipart request is rejected with 415. Not sure whether Apollo Gateway supports upload for comparison.
buffering the entire file before sending to the backend would have a huge effect on performance, this would make it very easy to DoS the server. And multipart upload has security issues, as explained in https://www.apollographql.com/blog/backend/file-uploads/file-upload-best-practices/
I'll look into how we could support it safely, but I can't make any promises on it. That would require:
- a way to make it safe against CSRF attacks
- an implementation that supports streaming upload
Yes, I think it would be ideal to send a pre-signed upload URL for the client to upload directly to cloud storage. It just requires more complicated logic around knowing when files have arrived to trigger the next step.
For now, we have exposed the subgraph publicly with duplicate auth logic to handle the upload directly. A streaming option would be great if it's feasible.
required feature IMO not sending things through the router isn't long term acceptable IMO. I'm having problems with it being impossible given it's possible with any proxy, though I can understand why it might be a challenge to stream it through a plugin or to a subgraph
I would probably look at any of the big http proxies and see how they handle it via straight http
@xenoterracide I can assure you we know how to make proxys and handle streaming protocols, that's not the issue here. Making something that is safe and works well with the subgraphs is the hard part, and file upload is not our focus right now
@Geal Do you have any recommendations on how to handle this? If there is no plan to provide a 1st party support for file uploads, is there an option to just proxy requests to a subgraph based on a header for example?
@Meemaw the current recommendations are listed here https://www.apollographql.com/blog/backend/file-uploads/file-upload-best-practices/
The signed URL solution is a bit cumbersome but works well in practice.
There is no support in the router for proxying the request body directly to a subgraph