简体   繁体   中英

graphql query with fetch producing 400 bad request

I am trying to write a basic graphql query with fetch that works when using apollo client. But it does not work with node-fetch.

The type definitions look like this:

type Query {
  findLeadStat(print: PrintInput!): LeadStatWithPrint
}

input PrintInput {
  printa: String!
  service: String
}

type LeadStatWithPrint {
  answered: Int!
  printa: String!
  service: String
}

This is the node-fetch query:

const fetch = require('node-fetch');

( async () => {    
    const uri = `http://localhost:3000/graphql/v1`;

    const query = `
        query findLeadStat(print: PrintInput!) {
          findLeadStat(print: $print){
            answered
            printa
            service
          }
        } 
    `;

    // I also tried add a query: key inside data object
    const data = {
            print: {
                printa: "62f69234a7901e3659bf67ea2f1a758d",
                service: "abc"
              }
    }

    const response = await fetch(uri, {
        method: 'post',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({query, data})
    });

    console.log('and the resp: ', response);
})()

It gives me:

url: 'http://localhost:3000/graphql/v1',
status: 400,
statusText: 'Bad Request',

It works in Apollo GraphQL Client. Why doesn't it work with fetch?

So when I was using async await with node-fetch, the response was pretty much useless. It was just telling me there was a 400 bad request error and then give me this long object of properties, none of them containing the actual error message.

But when I changed the fetch call to this:

const response = await fetch(uri, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query, variables}) // same as query: query, variables: variables
})
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error('ERROR: ', err));

There two lines right here:

.then(res => res.json())
.then(json => console.log(json))

made it clear what the issue was:

{
  errors: [
    {
      message: 'Syntax Error: Expected $, found Name "fingeprint"',
      locations: [Array],
      extensions: [Object]
    }
  ]
}

It appears node-fetch has two async events occurring and so await had to be used twice:

const response = await fetch(uri, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query, variables}) // same as query: query, variables: variables
})

console.log('and the resp: ', await response.json());

A 400 status indicates your query was invalid or malformed. When this happens, the response will include a JSON body with an errors array that can be inspected to determine what exactly went wrong.

In this particular case, the issue is that your query includes a non-nullable variable ( $print ) but this variable was not provided along with the query.

When making a GraphQL request, the request body should be a JSON object with a query property and two other optional properties -- variables and operationName . operationName is used to identify which operation to execute if multiple operations were included in the provided document (the query property). Any non-nullable variables defined in the executed operation must be included as properties under the variables property, which is also an object. Nullable properties may be omitted altogether.

In other words, you need to change the data property in your request to variables in order for the server to recognize that the variable was provided with the request.

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