Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
EnilPajic
@EnilPajic

Hi @PowerKiKi.
I have a question about graphql-upload. I've copied your example from github page and created schema as you described, but got this error:

Uncaught GraphQL\Server\RequestError: Unexpected content type: "multipart/form-data; boundary=------------------------0df73fd7442145cf" in $PROJECT$\vendor\webonyx\graphql-php\src\Server\Helper.php:515

Request is made via cURL as described here: https://github.com/jaydenseric/graphql-multipart-request-spec

This is my query (calling your function from example, removed the text parameter):

mutation TestUpload ($file: Upload) {
    testUpload (file: $file)
}

And when I pack this into cURL request, it looks like this (file save.txt is in the CWD):

curl localhost/test.php -F operations='{ "query": "mutation ($file: Upload!) { testUpload (file: $file) }", "variables": { "file": null } }' -F map='{ "0": ["variables.file"] }' -F 0=@"save.txt"

I've tried from windows (10) and linux (ubuntu server 16.04), but with no success. Version of cURL is 7.47.0 on linux and 7.58.0 on windows.

Tried also Insomnia client with body-type: multipart form, but the same exception is thrown with client-different message Unexpected content type: "multipart/form-data; boundary=X-INSOMNIA-BOUNDARY.

Searched through source code and found out that parsePsrRequest function throws this exception if content-type is not application/graphql or application/json and body is not an array. But it seems that array is sent (multiple -F options in cURL or in Insomnia).

This is the full exception stack trace:

Fatal error: Uncaught GraphQL\Server\RequestError: Unexpected content type: multipart/form-data; boundary=------------------------0df73fd7442145cf in $PROJECT$\vendor\webonyx\graphql-php\src\Server\Helper.php:515 
Stack trace: 
  #0 $PROJECT$\vendor\webonyx\graphql-php\src\Server\StandardServer.php(166): GraphQL\Server\Helper->parsePsrRequest(Object(Zend\Diactoros\ServerRequest)) 
  #1 $PROJECT$\test.php(56): GraphQL\Server\StandardServer->executePsrRequest(Object(Zend\Diactoros\ServerRequest)) 
  #2 {main} thrown in $PROJECT$\vendor\webonyx\graphql-php\src\Server\Helper.php on line 515

Also I'm using graphql-upload 2.0.1, graphql-doctrine 'dev-master' version (because dependencies are not updated for composer), graphql-php 0.11.5, zend-diactoros 1.7, and doctrine/orm 2.6.0.

Sorry for my english. So, if you may help me, to point me in the right direction how to upload file using your library because I cannot find example for doing it.

Thank you in advance! :)
Adrien Crivelli
@PowerKiKi
@EnilPajic "multipart/form-data" should never reach graphql-php, it should be intercepted by graphql-upload before and converted to "application/json". From what you said, I would guess that \GraphQL\Upload\UploadMiddleware is actually never called. How did you setup graphql-upload ?
EnilPajic
@EnilPajic
@PowerKiKi like you described on github page:
$schema ...

$schema->assertValid();
file_put_contents(__DIR__ . '/schema.graphql', \GraphQL\Utils\SchemaPrinter::doPrint($schema));
$server = new StandardServer([
    'schema' => $schema,
    'debug' => Debug::INCLUDE_DEBUG_MESSAGE | Debug::INCLUDE_TRACE
]);
$request = ServerRequestFactory::fromGlobals();

$request = $request->withParsedBody($x = json_decode($request->getBody()->getContents(), true));

$result = $server->executePsrRequest($request);
$uploadMiddleware = new UploadMiddleware();

$request = $uploadMiddleware->processRequest($request);
$server->getHelper()->sendResponse($result);
Adrien Crivelli
@PowerKiKi
are you using it as a middleware ? or as a direct usage ?
EnilPajic
@EnilPajic
Direct usage @PowerKiKi
Adrien Crivelli
@PowerKiKi
$request = $uploadMiddleware->processRequest($request); should come before executePsrRequest()
double check the docs, it's basically:
  1. Create request (or get it from a framework)
  2. Process uploaded files
  3. Execute request and emits response
EnilPajic
@EnilPajic
Yea, I figured it out the moment I pasted it here! Now I'm experiencing another exception (PSR-7 request is expected to provide parsed body for "multipart/form-data" requests but got null) but I'll try to handle that myself
Thank you very much, how silly of me! :(
Adrien Crivelli
@PowerKiKi
this might be because you json_decode twice
once in the graphql-upload, and once yourself
you should probably add something like if (!is_array($request->getBody()->getContents()) { json_decode...
EnilPajic
@EnilPajic
Hmmm, I cannot see the "another" json_decode, only the one you provided in $request = $request->withParsedBody($x = json_decode($request->getBody()->getContents(), true)); (if I var_dump the $x variable I got NULL, so it means it is json_decoded before...)
Hmmm, var_dump($request->getBody()->getContents()); emits the string(0) ""
Is this the right way?
curl localhost/test.php -F operations='{ "query": "mutation ($file: Upload!) { testUpload (file: $file) }", "variables": { "file": null } }' -F map='{ "0": ["variables.file"] }' -F 0=@"save.txt"
and sorry for bugging you :(
Adrien Crivelli
@PowerKiKi
i'm not quite sure about the curl command... don't you have some single/double quotes issues in there ?
the best would be to dump what you get in PHP
Adrien Crivelli
@PowerKiKi
it seems the curl command might right...
EnilPajic
@EnilPajic

Quotes are OK (copied from Insomnia the query and used JSON Lint to be sure it is ok), but...
If you mean to var_dump like this:

$request = ServerRequestFactory::fromGlobals();
var_dump($request);

Then the var_dump output is really big, but here is the line that is interesting:
["file":"Zend\Diactoros\UploadedFile":private]=> string(23) "C:\WAMP\tmp\phpDB91.tmp"

Or you are asking something else?

Adrien Crivelli
@PowerKiKi
not sure what I am asking for ^^
EnilPajic
@EnilPajic
Hahahah, thank you for your time! I really appreciate it! :D
Adrien Crivelli
@PowerKiKi
no worries, I hope you find what's wrong... it might be something in graphql-upload, because we used in only two specific contexts, maybe there are cases that are not yet handled correctly...
EnilPajic
@EnilPajic

In case somebody has similar problem, there is a solution that worked for me:

  • (1) cURL strings should be escaped via double-quotes (") not single quotes. I'm not sure why it doesn't work for me when I use single-quotes because cURL seems to supports both. So, my current working cURL command is:

    curl localhost/unis/test.php -F operations="{\"query\": \"mutation ($file: Upload!) { testUpload (file: $file) }\", \"variables\": {\"file\": null }}" -F map="{\"0\" : [\"variables.file\"] }" -F 0=@"save.txt"
    • (1.1.) if uploading via Insomnia (or other REST/GraphQL client I guess), body type should be Multipart Form, and there you should set fields: operations, map and so on, exactly like via cURL. See this image for more info.
  • (2). There is no need for json_decodeing body. I'm no expert, but my $request->getBody()->getContents() is an empty string every time, so, json_decode will return NULL and request will fail. When var_dumping $request->getParsedBody() I get the passed variables (that is how I figured out that single quotes don't work, parsed body was trimmed). Also, the soultion provided above (if (!is_array($request->getBody()->getContents())) will not work because empty string is not an array. I skipped the line that containts withParsedBody. Unsure if this is only for me, or.... but it works (at least for me) :D

The final PHP code that works for me is:

$server = new StandardServer([
    'schema' => $schema,
    'debug' => Debug::INCLUDE_DEBUG_MESSAGE | Debug::INCLUDE_TRACE
]);
$request = ServerRequestFactory::fromGlobals();
#$request = $request->withParsedBody(json_decode($request->getBody()->getContents(), true)); #SKIPPED


$uploadMiddleware = new UploadMiddleware();
$request = $uploadMiddleware->processRequest($request);

$result = $server->executePsrRequest($request);
$server->getHelper()->sendResponse($result);

Thank you Adrien for these two really useful libs (-doctrine and -upload), and, of course, than you for helping me today!

Best regards,
Enil.

Adrien Crivelli
@PowerKiKi
thank you for reporting back
Mohit Kumar
@mohitsid31_gitlab

Hello,

I have installed this plugin by composer, so can anyone help me how i can use it?

Adrien Crivelli
@PowerKiKi
@mohitsid31_gitlab everything you need to know should be in the docs: https://github.com/Ecodev/graphql-upload#quick-start