简体   繁体   中英

GraphQL file upload plain JS "Must provide query string."

I am uploading files to GraphQL API with plain JS. I've been doing this from the same origin for months now and now am trying to implement the exact same thing externally with NodeJS.

My code looks something like this:

const FormData = require('form-data');
const fs = require('fs')
const axios = require('axios')

const payload = generateRequest(input)

axios.post(apiBaseUrl + "/graphql", payload, {
      headers: {...payload.getHeaders()}
    }).then(response => {
        let res = response.data
        if (res.data.triggerPcWorkflow.status === 200) {
            console.log("success!")
        } else {
            console.error(res.data.triggerPcWorkflow.message)
        }
      })
      .catch(err => {
          if (err.response) {
              console.log(err.response.data);
              console.log(err.response.status);
              console.log(err.response.headers);
          }
      })

With the generateRequest function generating the multipart payload ( https://github.com/jaydenseric/graphql-multipart-request-spec ).

I have two identical versions of the Backend running on localhost:5000 and mycooldomain.com . When setting apiBaseUrl to http://localhost:5000 everything works flawlessly. However just by changing the URL to https://www.mycooldmain.com I get a 400 error thrown at me with { errors: [ { message: 'Must provide query string.' } ] } { errors: [ { message: 'Must provide query string.' } ] }

BTW: A simple query works with both URLs...

Here is my generateRequest function:

const mutation = `
mutation MyMutation($xyz: String) {
    doSomething(myInput: $xyz) {
        status 
        message
    }
}
`

let sendData = new FormData();
const fileNull = [];
    
// map
files = generateRequestInput.files
let map = '{'

for (let i = 0; i < files.length; i++) {
  fileNull.push(null);
  map += `"${i}": ["variables.files.${i}"], `
}

map = map.substring(0, map.length-2);
map += '}'

// operations
const operations = JSON.stringify({
    query: mutation,
    variables: {
        "xyz": "Hello"
    }
  });

// build payload
sendData.append("operations", operations)
sendData.append("map", map)
for (let i = 0; i < files.length; i++) {
    sendData.append(i, files[i]);
}

return sendData

I know that map looks a bit ugly but thats not the point (unless it is).

Has anyone had a similar problem or knows what my error is here? Thanks!

I skipped on the axios dependency and implemented the request with FormData directly.

The code below works.

function makeRequest(formData, options) {
  formData.submit(options, (err, res) => {
    if (err) {
      console.error(err.message)
      return
    } else {
      
      if (res.statusCode < 200 || res.statusCode > 299) {
        console.error(`HTTP status code ${res.statusCode}`)
      }
      
      const body = []
      res.on('data', (chunk) => body.push(chunk))
      res.on('end', () => {
        const resString = Buffer.concat(body).toString()
        console.log(resString)
      })
    }
  })
}

const options = {
  host: 'mycooldomain.com',
  port: 443,
  path: '/graphql',
  method: 'POST',
  protocol: 'https:'
}

makeRequest(payload, options)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM