Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an ability to upload files #84

Open
ssbb opened this issue Nov 18, 2018 · 4 comments
Open

Add an ability to upload files #84

ssbb opened this issue Nov 18, 2018 · 4 comments

Comments

@ssbb
Copy link

ssbb commented Nov 18, 2018

It will be good to add something like withFiles : List ( String, File.File ) -> Request decodesTo -> Request decodesTo so it will be possible to upload files alongside with query.

It will require to send request as POST with multipart/form-data though so it will overwrite things like QueryRequestMethod silently.

Sending files over GraphQL is not a part of official spec but supported by many frameworks:

@dillonkearns
Copy link
Owner

Hey @ssbb, thank you for opening the issue!

It looks like both the Absinthe and multipart-request-spec use a Scalar type called Upload. I tried generating some code using an Absinthe test server and it generated this with dillonkearns/elm-graphql:

module Swapi.Scalar exposing (..)
# ...

type Upload
    = Upload String
module Query exposing (..)
# ...
type alias SendFileRequiredArguments =
    { file : Swapi.Scalar.Upload }


sendFile : SendFileRequiredArguments -> Field String RootQuery
sendFile requiredArgs =
    Object.fieldDecoder "sendFile" [ Argument.required "file" requiredArgs.file (\(Swapi.Scalar.Upload raw) -> Encode.string raw) ] Decode.string

Given that this is treated like a special type, it seems like it would be nice to treat this scalar as a special thing and require a file to be passed in here.

So the generated code could just change the underlying type of the scalar

type Upload
    = Upload File

The Encode module would then have to take on some more complexity, doing more than just turning it into a simple GraphQL query... instead, it would have to encode the files as nulls, or [null, null] lists. Then the Graphql.Http module would have to look for any files and figure out where to send them somehow... Anyway, that will be a pretty major design process and will require some thought.

But I think that it's worth experimenting with that approach. Just adding a Graphql.Http.withFiles function that let's you manually add in files which may not be under the correct keys... or that lets you forget to add files, etc., just doesn't feel right given the goals of the library to guarantee correctness. I wouldn't want it to be that it "guarantees correct queries, unless you add files"!

What do you think?

@ssbb
Copy link
Author

ssbb commented Nov 19, 2018

Hi @dillonkearns, thanks for quick detailed reply 👍

I am not sure it's good idea to rely on Upload just by name. It can be used for other purposes as well. Maybe when #39 will be implemented?

My idea was to give a bit more control over HTTP request. Files can be not related to GraphQL at all, right? Like you sending normal GraphQL query and files at the same time (w/o affecting query with things like Upload scalar at all) and back-end know how to work with it. But files here not related to GraphQL at all.

BTW graphql-multipart-request-spec using a bit different approach - request should contain map field with JSON-encoded field/file mapping.

@pdamoc
Copy link

pdamoc commented Jan 24, 2023

A small bump to this issue as I ran into it today with a gqlgen server.

I had to bypass elm-graphql by manually creating the query and using a request with Http.multipartBody.

@dillonkearns
Copy link
Owner

Hey @pdamoc , the last I checked file uploads weren't part of the spec in a concrete and standardized way, so I'm actually not sure there a clear and actionable thing that can be done here that follows a the spec.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants