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

Upload not working to Apollo Server using v0.13.0 #698

Closed
Cleversou1983 opened this issue Aug 7, 2019 · 3 comments
Closed

Upload not working to Apollo Server using v0.13.0 #698

Cleversou1983 opened this issue Aug 7, 2019 · 3 comments
Labels
docs Focuses on documentation changes question Issues that have a question which should be addressed

Comments

@Cleversou1983
Copy link

Hello! I'm struggling to make a file upload to a server, I've opened this issue to report everything steps, from IOS to the Apollo Server logs:

To show that our GQL Server is compliant with the standard here is a success CURL real example:

/// APOLLO SERVER

curl http://madari-staging.herokuapp.com/graphql
-F operations='{ "query": "mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image clientId: $clientId, clientSecret: $clientSecret } ) { errors attachment { id } } }", "variables": { "clientId": "fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs", "clientSecret": "wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw", "image": null } }'
-F map='{ "0": ["variables.image"] }'
-F 0=@oren\ Logo.png

That hit a real public test server with a custom ID and Secret we made it for you to be able to test so, fell free to run that any time.
For comparison reasons, the above shows the following log on the Rails Server:
019-08-07T18:15:45.805200+00:00 app[web.1]: I, [2019-08-07T18:15:45.805101 #4] INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] Processing by Public::GraphqlController#execute as /
2019-08-07T18:15:45.805448+00:00 app[web.1]: I, [2019-08-07T18:15:45.805334 #4] INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] Parameters: {"operations"=>"{ "query": "mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image clientId: $clientId, clientSecret: $clientSecret } ) { errors attachment { id } } }", "variables": { "clientId": "fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs", "clientSecret": "wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw", "image": null } }", "map"=>"{ "0": ["variables.image"] }", "0"=>#<ActionDispatch::Http::UploadedFile:0x00007ffa8c869f50 @tempfile=#Tempfile:/tmp/RackMultipart20190807-4-16tyea8.png, @original_filename="Oren Logo.png", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name="0"; filename="Oren Logo.png"\r\nContent-Type: application/octet-stream\r\n">, "query"=>"mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image clientId: $clientId, clientSecret: $clientSecret } ) { errors attachment { id } } }", "variables"=>{"clientId"=>"fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs", "clientSecret"=>"wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007ffa8c869f50 @tempfile=#Tempfile:/tmp/RackMultipart20190807-4-16tyea8.png, @original_filename="Oren Logo.png", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name="0"; filename="Oren Logo.png"\r\nContent-Type: application/octet-stream\r\n">}}

........

2019-08-07T18:15:46.777150+00:00 app[web.1]: I, [2019-08-07T18:15:46.777065 #4] INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] [ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 3a71cfa8-e599-49ea-b013-da68f3e26ea3) to Async(default) with arguments: #<GlobalID:0x00007ffa8c6c1bd0 @uri=#<URI::GID gid://madari/ActiveStorage::Blob/58>>
2019-08-07T18:15:46.779655+00:00 app[web.1]: I, [2019-08-07T18:15:46.779570 #4] INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] Completed 200 OK in 974ms (Views: 0.3ms | ActiveRecord: 18.6ms)

////// IOS

let fileFieldName = "file"
let file = GraphQLFile(fieldName: fileFieldName, originalName: fileFieldName, mimeType: "image/jpeg", data: imageData)

        let uploadInput     = UploadFileInput(clientId: AppParameters.clientId,
                                          clientSecret: AppParameters.clientSecret,
                                          file: fileFieldName)
        
        let uploadMutation = UploadFileMutation(image: "", clientID: AppParameters.clientId, clientSecret: AppParameters.clientSecret)
        
        let configuration = URLSessionConfiguration.default

        let transport   = HTTPNetworkTransport(url: AppParameters.APIPublicUrl, configuration: configuration)
        let upload      = transport.upload(operation: uploadMutation, files: [file]) { result in
            switch result {
            case .success(let data):
                print("Success")
                dump(data)
            case .failure(let error):
                print("Error \(error.localizedDescription)")
            }
        }
...
2019-08-07T18:14:07.336809+00:00 app[web.1]: ��r��X��F�y2��+g$�
2019-08-07T18:14:07.336810+00:00 app[web.1]: rZ�>��޷�����<p=��G$Z6��	�\�TN�d
                                                                               ���o���PG�r�f
2019-08-07T18:14:07.336812+00:00 app[web.1]: m�|�6�rM2�FLO��
2019-08-07T18:14:07.336813+00:00 app[web.1]: ���1C�6s��|�w�cN���[�zW8�3��[���s��$"3!<��c�Cn%
                                                                                            �N@�닄�qԚd�a2�禘J�y�3d�.��ϔ��cV�7w�8�3�9�!,2�c�2H��\m�k�x=+��J�v�������:���8�37SVev�0Gzʸ|-|�G�ެ�#��'9����y�7�S�f��-Up�r�㹪N�d�G���J�v
2019-08-07T18:14:07.336815+00:00 app[web.1]: rEr�G��B�[��
2019-08-07T18:14:07.336816+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF--
2019-08-07T18:14:07.337714+00:00 app[web.1]: F, [2019-08-07T18:14:07.337599 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806]
2019-08-07T18:14:07.337783+00:00 app[web.1]: F, [2019-08-07T18:14:07.337729 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806] ActionDispatch::Http::Parameters::ParseError (765: unexpected token at '--apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337785+00:00 app[web.1]: Content-Disposition: form-data; name="query"
2019-08-07T18:14:07.337787+00:00 app[web.1]:
2019-08-07T18:14:07.337788+00:00 app[web.1]: mutation UploadFile($image: Upload!, $clientID: String!, $clientSecret: String!) {
2019-08-07T18:14:07.337790+00:00 app[web.1]: uploadFile(input: {file: $image, clientId: $clientID, clientSecret: $clientSecret}) {
2019-08-07T18:14:07.337792+00:00 app[web.1]: __typename
2019-08-07T18:14:07.337793+00:00 app[web.1]: attachment {
2019-08-07T18:14:07.337795+00:00 app[web.1]: __typename
2019-08-07T18:14:07.337796+00:00 app[web.1]: id
2019-08-07T18:14:07.337798+00:00 app[web.1]: }
2019-08-07T18:14:07.337799+00:00 app[web.1]: errors
2019-08-07T18:14:07.337800+00:00 app[web.1]: }
2019-08-07T18:14:07.337802+00:00 app[web.1]: }
2019-08-07T18:14:07.337804+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337805+00:00 app[web.1]: Content-Disposition: form-data; name="variables"
2019-08-07T18:14:07.337807+00:00 app[web.1]:
2019-08-07T18:14:07.337808+00:00 app[web.1]: {"image":"","clientID":"fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs","clientSecret":"wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw"}
2019-08-07T18:14:07.337810+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337811+00:00 app[web.1]: Content-Disposition: form-data; name="operationName"
2019-08-07T18:14:07.337813+00:00 app[web.1]:
2019-08-07T18:14:07.337814+00:00 app[web.1]: UploadFile
2019-08-07T18:14:07.337816+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337817+00:00 app[web.1]: Content-Disposition: form-data; name="file"; filename="file"
2019-08-07T18:14:07.337819+00:00 app[web.1]: Content-Type: image/jpeg
2019-08-07T18:14:07.337820+00:00 app[web.1]:
2019-08-07T18:14:07.337822+00:00 app[web.1]: ����'):
2019-08-07T18:14:07.337826+00:00 app[web.1]: F, [2019-08-07T18:14:07.337787 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806]
2019-08-07T18:14:07.337917+00:00 app[web.1]: F, [2019-08-07T18:14:07.337848 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/parameters.rb:117:in `rescue in parse_formatted_parameters'
2019-08-07T18:14:07.337920+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/parameters.rb:111:in `parse_formatted_parameters'
2019-08-07T18:14:07.337922+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/request.rb:381:in `block in POST'
2019-08-07T18:14:07.337925+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/request.rb:59:in `fetch'
2019-08-07T18:14:07.337927+00:00 app[web.1]: [0be539e3-58c8-40a6-8

Hope you can help me with that... Thanks a lot!!!

@designatednerd
Copy link
Contributor

Firstly, please check out #695 to see if any of the suggestions there help you. If they do, you can skip the rest of this, just let us know what helped.

If they don't, I have a few questions for you:

  • Am I correct from reading the logs that your actual GraphQL mutation is:

    mutation UploadFile($image: Upload!, $clientID: String!, $clientSecret: String!) {
      uploadFile(input: {file: $image, clientId: $clientID, clientSecret: $clientSecret}) {
        __typename
        attachment {
          __typename
          id
        }
        errors
      }
    }
  • Why is input using a {bunch of variables surrounded by a closure} instead of an InputType?

  • Why are errors specified in the query? Normally these should be returned as an error state, not as an additional type.

@designatednerd designatednerd added docs Focuses on documentation changes question Issues that have a question which should be addressed labels Aug 7, 2019
@Cleversou1983
Copy link
Author

Cleversou1983 commented Aug 7, 2019

Hi, @designatednerd ! This was a trial and error... I've tried with upload Input as well, as you can see here...

/// SWIFT
if let imageData = image.jpegData(compressionQuality: 0.7) {

        let fileFieldName   = "file"
        let file            = GraphQLFile(fieldName: fileFieldName, originalName: fileFieldName, mimeType: "image/jpeg", data: imageData)

        let uploadInput     = UploadFileInput(clientId: AppParameters.clientId,
                                          clientSecret: AppParameters.clientSecret,
                                          file: fileFieldName)
        
        
        let uploadMutation = UploadFileMutation(input: UploadFileInput)
        
        let configuration = URLSessionConfiguration.default

        let transport   = HTTPNetworkTransport(url: AppParameters.APIPublicUrl, configuration: configuration)
        let upload      = transport.upload(operation: uploadMutation, files: [file]) { result in
             self.UIManager.enableUI()

            switch result {
            case .success(let data):
                print("Success")
                dump(data)
            case .failure(let error):
                print("Error \(error.localizedDescription)")
            }
        }
    }

// MUTATION
mutation UploadFile($input: UploadFileInput!){
uploadFile(input: $input){
attachment{
id
}
errors
}
}

/// ERRORS
"Why are errors specified in the query? Normally these should be returned as an error state, not as an additional type." These are the message errors that the server may return to me...

I really appreciate your help!

@designatednerd
Copy link
Contributor

Hey - so looking at the stack trace, the server is throwing an error in Ruby here. What server are you using - the whole Apollo Server is written in JS, so it's some other GraphQL server.

I believe as I indicated in #695 you'll need to talk to your backend dev - I didn't realize when I replied last night that you'd also started that issue as well. Can we pick one of these issues to focus on please?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Focuses on documentation changes question Issues that have a question which should be addressed
Projects
None yet
Development

No branches or pull requests

2 participants