1

If I do a GraphQL query usinge node-fetch or curl I get back the expected results. For example, if I have a file gquery.js with the following code:

const fetch = require("node-fetch")
fetch('https://api.example.com/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Api-Service-Key': '123456789077',
  },
  body: JSON.stringify({query: "query($fruitId: String!) { fruit(id: $fruitId) { id, name } }",
  variables: { "fruitId": "ikttwwwbvn7" }})
})
  .then(r => r.json())
  .then(data => console.log('data returned:', data));

And on my Ubuntu machine I just run $node gquery.js I get back a result. I'll also get a result if I use plain curl, e.g.:

curl -H 'Content-Type: application/json' -X POST -H "X-Api-Service-Key: 123456789077" https://api.example.com/graphql -d '{ "query": "query($fruitId: String!) { fruit(id: $fruitId) { id, name } }", "variables": { "fruitId": "ikttwwwbvn7" }}'

However, if I just use fetch on Chrome, e.g.:

fetch('https://api.example.com/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Api-Service-Key': '123456789077',
  },
  body: JSON.stringify({query: "query($fruitId: String!) { fruit(id: $fruitId) { id, name } }",
  variables: { "fruitId": "ikttwwwbvn7" }})
})
  .then(r => r.json())
  .then(data => console.log('data returned:', data));

I get an error:

Access to fetch at 'https://api.example.com/graphql' from origin 'chrome-search://local-ntp' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Note: My endpoint is actually different, but otherwise this example is essentially the same as what I have.

I had a look at a related question, but answers seem to suggest that this cannot be resolved on the client side only. But the fact that I can use curl and node successfully tells me that I just don't have the right code.

To be clear, I don't really care about fetch. I'm happy to use any standalone Javascript solution that does not require the use of a client like apollo or relay.

8
  • 2
    The fetch API is what you are looking for. But in a browser, you're just limited by the same origin policy, there's nothing you can do about that. Commented Feb 7, 2020 at 16:32
  • 2
    node-fetch is server-based (because it's node). It isn't bound by the CORS policy, it can do whatever it wants. fetch is the browser equivalent for fetch. The problem is that browser JS is bound by CORS policy and there is no way to circumvent it outside of fetching from your own proxy server which you have to host. Commented Feb 7, 2020 at 16:32
  • Thanks, I'm looking for code solutions. I know that there are Javascript GraphQL clients like relay and apollo, but I thought there must be a way to construct a simple query in JavaScript that I can run on the browser. But if the answer is "it's impossible and this is why...", I can accept that. I'll change my question to reflect what I want to achieve. Commented Feb 7, 2020 at 16:43
  • Those libraries would be subject to exactly the same restriction. You need to fix the CORS policy of your server, use a proxy on your domain, or something else. Also, what exactly is the environment that your js code is running in? "origin 'chrome-search://local-ntp'" looks weird. Commented Feb 7, 2020 at 16:55
  • 1
    @Nagev "How to do a simple GraphQL query in JavaScript" is a different question than your original question. What are you asking for, how to do a GraphQL query request using JavaScript in the browser? Or how to fix the CORS error that you're seeing in your browser when you try to make a GraphQL request? Commented Feb 7, 2020 at 16:55

2 Answers 2

3

There's no way to get around the same-origin policy enforced by browsers. You don't encounter the same issue when sending your request through curl or node because the same-origin policy is not enforced in those contexts. It is always enforced in the browser unless you explicitly disable it. Preventing cross-domain requests is an import security measure, though, so disabling it is generally inadvisable.

There's nothing magical about how GraphQL clients like Apollo work. They still use fetch under the hood. If you're hitting a CORS issue using fetch, you'd hit the same issue using Apollo or any other browser-based client. If you use a standalone client like Postman or Altair, you won't because, again, you're not dealing with a browser.

As suggested in the post you linked, this is an issue that has to be addressed on the server-side. If you're not making requests to your own server, the only viable workaround is to utilize a proxy. You can utilize an existing one or run your own.

Sign up to request clarification or add additional context in comments.

Comments

0

You can pass "{mode: 'no-cors'}". Please check the given reference.

fetch(
 'https://api.example.com/graphql',
 {
  mode: 'no-cors' 
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Api-Service-Key': '123456789077',
  },
  body: JSON.stringify({
   query: "query($fruitId: String!) { fruit(id: $fruitId) { id, name } }",
   variables: { "fruitId": "ikttwwwbvn7" }
  })
 }
)
.then(r => r.json())
.then(data => console.log('data returned:', data));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.