1

I'm trying to upload an image to KeystoneJS. The image corresponds to the KeystoneJS list Image, with the following GraphQL schema

mutation createImage(data: ImageCreateInput): Image

input ImageCreateInput {
  file: Upload
}

I'm uploading from TinyMCE, which here is a custom field inside the KeystoneJS AdminUI. Following the following instructions (How can one upload an image to a KeystoneJS GraphQL endpoint?) I'm using Apollo-upload-client to upload the image, which apparently is already installed in the AdminUI as the Apollo Client. Following the Apollo-upload-client docs I am uploading the blob from inside the TinyMCE images_upload_handler

const UPLOAD_MUTATION = gql`mutation upload($data: ImageCreateInput!) {
    createImage(data: $data) {
      id
      file {
        path
        filename
      }
    }
  }
`;

images_upload_handler: function(blobInfo, success, failure) {

            const image = blobInfo.blob();
            try {
                log.debug('about to mutate');
                log.debug(client);
                client.mutate(
                {
                mutation: UPLOAD_MUTATION,
                variables: { data: { file: image } }
                }
                ).then(result => {
                log.debug('result');
                log.debug(result);
                success(result);
                });
                } catch (e) {
                log.debug('error', e.toString());
            failure(e);
            }
    }

however KeystoneJS logs the following error, complaining of Missing multipart field 'operations'.

{"level":50,"time":1584092923059,"pid":29020,"hostname":"somewhere.or.other","name":"graphql","message":"Missing multipart field ‘operations’ (https://github.com/jaydenseric/graphql-multipart-request-spec).","extensions":{"code":"INTERNAL_SERVER_ERROR"},"uid":"ck7q00y3x0000e4rjfevaapo3","stack":"\n module.exports (node_modules/ensure-error/index.js:28:16)\n _formatError (node_modules/@keystonejs/app-graphql/lib/apolloServer.js:97:44)\n
node_modules/apollo-server-errors/dist/index.js:167:34\n Array.map ()\n Object.formatApolloErrors (node_modules/apollo-server-errors/dist/index.js:165:27)\n
node_modules/apollo-server-express/dist/ApolloServer.js:47:39\n
runMicrotasks ()\n","name":"BadRequestError","v":1}

The network response is

Summary
URL: http://localhost:4545/admin/api
Status: 400 Bad Request
Source: Network
Address: ::1:4545

Request
POST /admin/api HTTP/1.1
Cookie: keystone.sid=s%3A2OXYDUkDenT3i6yu3lVQpSafC3AQ_5vq.XiOyB1gahSc%2FFjaNq36dnEIL4Vk0VwR%2FBq6lY7NDLyk
Accept: */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDjNz6A1qrij1s1Ye
Origin: http://localhost:4545
Content-Length: 10871
Accept-Language: en-us
Host: localhost:4545
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1.1 Safari/605.1.15
Referer: http://localhost:4545/admin/articles/5e6a119a07e2e826a71b0cf5
Accept-Encoding: gzip, deflate
Connection: keep-alive

Response
HTTP/1.1 400 Bad Request
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'
Content-Type: text/html; charset=utf-8
Date: Fri, 13 Mar 2020 13:18:09 GMT
Connection: keep-alive
Vary: Origin
Content-Length: 142
Access-Control-Allow-Origin: *
X-Keystone-App-Version: 1.0.0
X-Powered-By: Express

Request Data
MIME Type: multipart/form-data
Boundary: ----WebKitFormBoundaryDjNz6A1qrij1s1Ye
Request Data: 

------WebKitFormBoundaryDjNz6A1qrij1s1Ye
Content-Disposition: form-data; name="operations"

{"operationName":"upload","variables":{"data":{"file":null}},"query":"mutation upload($data: ImageCreateInput!) {\n  createImage(data: $data) {\n    id\n    file {\n      path\n      filename\n      __typename\n    }\n    __typename\n  }\n}\n"}
------WebKitFormBoundaryDjNz6A1qrij1s1Ye
Content-Disposition: form-data; name="map"

{"1":["variables.data.file"]}
------WebKitFormBoundaryDjNz6A1qrij1s1Ye
Content-Disposition: form-data; name="1"; filename="blip.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryDjNz6A1qrij1s1Ye--

I'm a relative newbie with GraphQL and the answers I've found regarding this error and apollo-upload-client seem addressed to those mounting their own Apollo Servers, whereas I'm working with something already set up.

halfer
  • 19,824
  • 17
  • 99
  • 186
Cerulean
  • 5,543
  • 9
  • 59
  • 111
  • 1
    If you look at the request in your browser's dev tools, does it look like a multi-part request? It should look somewhat [like this](https://stackoverflow.com/questions/41188903/what-does-webkitformboundary-mean), with the first part containing `Content-Disposition:form-data; name="operations"`. – Daniel Rearden Mar 13 '20 at 11:00
  • @DanielRearden, I've added the network response above. Indeed, it does say `Content-Disposition: form-data; nam="operations"` – Cerulean Mar 13 '20 at 13:22
  • 1
    So it would appear that the client is doing what it's supposed to do -- at this point I would say it's a server issue, so you may need to open an issue with KeystoneJS. – Daniel Rearden Mar 13 '20 at 14:14

0 Answers0