25

I have searched all over StackOverflow and saw similar questions but have not found a working solution. Wondering if anyone has a working solution? I am developing a create react app on localhost:3000 and trying to access through my Apollo Client a URI on a different site (I am testing with https://developer.github.com/v4/explorer/).

I have added the fetchOptions mode of 'no-cors' to my new ApolloClient instance but I am still getting a CORS error in my console. My enitre index.js file is below:

import React from 'react';
import ReactDOM from 'react-dom';

import { ApolloProvider } from 'react-apollo';
import { ApolloClient, HttpLink, InMemoryCache } from 'apollo-boost';

import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';


const client = new ApolloClient({
    link: new HttpLink({ uri: 'https://developer.github.com/v4/explorer/' }),
    fetchOptions: {
        mode: 'no-cors',
      },
    cache: new InMemoryCache()
  });
  
  const AppWithProvider = () => (
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  );
ReactDOM.render(<AppWithProvider />, document.getElementById('root'));


serviceWorker.unregister();

Error message in console: Access to fetch at 'https://developer.github.com/v4/explorer/' from origin 'http://localhost:3000' 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.

Antoni
  • 1,316
  • 2
  • 16
  • 42
Elaine
  • 383
  • 1
  • 5
  • 10
  • 1
    You're making a cross-origin request, you must conform to the CORS policy. Setting `mode: 'no-cors'` doesn't magically circumvent the CORS policy enforced by modern web browsers. If `https://developer.github.com` does not set the `AccessControl-Allow-Origin` header then you cannot make cross-origin requests to that resource. – Jake Holzinger Sep 13 '19 at 21:31
  • 9
    @JakeHolzinger Your comment is not helpful to the question because any public API you use with Apollo Client will have this CORS error with localhost development. Please try and recreate it with the setup above so that you can see what the question is asking. If you can provide a solution instead using this exact Apollo setup of how you develop locally with any public API without CORS issue, it would be more helpful. – Elaine Sep 16 '19 at 02:25
  • it is up to the API developer to choose whether or not they will accept cross-origin requests. I do not have a magic solution that makes cross-origin requests work for every API. You can implement your own API that then makes requests to the github API from the server, but in the browser you do not get to decide what the server response will be. – Jake Holzinger Sep 16 '19 at 03:15

3 Answers3

1

In order for CORS to work, the server needs to be configured to support your host (in this case localhost). However, CORS is not needed for server-to-server communication, so what you typically do is set up a proxy.

Create-react-app has built-in support for setting up such a proxy: https://create-react-app.dev/docs/proxying-api-requests-in-development/.

peternyc
  • 581
  • 3
  • 8
  • We use this pattern a lot, here's a link to the same functionality in webpack dev server: https://webpack.js.org/configuration/dev-server/#devserverproxy. The Apollo client is of course pointed towards this proxy. – Johan Nordlinder Mar 29 '22 at 18:15
0

As the API endpoint will likely not have "localhost" in its Access-Control-Allow-Origin, you have to choose between an easy and a clean solution.

  1. The easy solution: if it is just for dev-purposes, you could consider starting e.g. Chrome with the --disable-web-security flag set. As this greatly reduces security however, it should only be a temporary solution for development purposes.

  2. The clean solution: if the API endpoint does not have Access-Control-Allow-Origin: '*', there is no real way to fully consume data from a browser. Consider having the back-end of your application send the requests to the API endpoint and then make the result available to your front-end.

daniel f.
  • 1,421
  • 1
  • 13
  • 24
0

I've also encountered this same issue recently.

A solution to how I resolved this issue: The browser sends a method=OPTIONS request. i.e a pre-flight request in Cross-origin resource sharing (CORS). So in order to solve this issue. Just add a middleware in your backend like this.

app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Methods",
    "OPTIONS, GET, POST, PUT, PATCH, DELETE"
  );
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  if (req.method === "OPTIONS") {
    return res.sendStatus(200);
  }
  next();
});