-1

I'm getting fairly tripped up and likely burning up too much brain energy over an issue with trying to use the Fetch API to retrieve a JSON data resource (of earthquake data) from an existing resource page.

To be up front, the task I'm attempting to tackle here is to complete an assessment for an interview, however, I didn't expect my efforts in this to be thwarted soon after beginning the assessment in the first code written: fetching a JSON data structure to be parsed, manipulated, and the rendered in an application built from Create-React-App.

The fetch is being made from inside the componentDidMount lifecycle inside a component designed primarily for retrieving and parsing the data:

componentDidMount() {
  fetch('http://sitetest.test.com/seismic/data.json', {
    credentials: 'include',
  })
    .then(response => {
      console.log(response);
      response.json();
    })
    .then(earthquakes => {
      this.setState({ earthquakes });
    })
    .catch(error => {
      console.log('====failure====');
      console.log(error);
    });
}

The simplest fetch request causes a CORS conflict to be reported to the console:

Console: CORS conflict

I spent a good bit of time reading into why the CORS conflict is being reported. Ultimately, the explanations I've read boil down to what is reported in the error output, that:

"No 'Access-Control-Allow-Origin' header is present on the requested resource."

As I've researched into possible solutions to resolve the CORS issue, I've read things like "it's impossible to resolve this unless you have access to the origin's server code itself" here, that the body of the JSON object I'm trying to retrieve can be gotten through setting up a proxy (still haven't been successful with this method).

Perhaps I just don't have enough understanding with how Fetch is wielded in such situations. What I'd like to do is try to investigate the problem by having my failing fetch request at least report some information to the console about the resource's headers which explictly shows how "No 'Access-Control-Allow-Origin' header is present on the requested resource.", but perhaps I should simply be satisfied with checking the Network pane in the console over on the resource page:

JSON Resource Page: Network Report Right-click to view this image in a separate tab

Puzzling over this information reported in each the Response and Request Headers report, I just know someone with more experience in making asynchronous requests for data would point out what would be obvious to them in resolving the CORS conflict. My latest attempt to work around the CORS issue in my above code was to include the credentials in the options object passed into fetch. This idea occurred to me while reading over MDN's article on Using Fetch which, as I understood, would include the appropriate cookie if this type of auth configuration were encountered while making the request. There is a long, abstract (collection?) of cookie value(s) in the resource's Request Headers report, but attempting to include what I believed was the necessary means of handing off the needed cookie in my fetch request has proven unsuccessful.

In my research into this problem, I'm not finding too much that is relatable enough to my scenario which would indicate a good approach for resolving the CORS problem. I feel pretty lost and could really use some guidance. Perhaps someone could either point out a good resource for dealing with a number of different fetch operations, because as someone who is essentially self-taught, a lot of the web resources I've consulted so far: MDN, forums, Medium articles haven't allowed me to clearly piece together how to circumvent the CORS policy with the appropriate modifier to my fetch request.

Any ideas?

Looking forward to moving on from here, as the remainder of this task involves passing data around inside the React application which I feel I have plenty enough experience to overcome.

Jetals
  • 131
  • 1
  • 2
  • 10
  • 1
    If it were possible to "work around a CORS issue" with code on the page, that would represent a massive security problem and the "fix" would be patched in a hurry. – Pointy Mar 03 '19 at 18:46
  • 2
    You say this is for an interview; did they provide this resource? Do you think they want you to work around CORS? Or perhaps you can use a different data source that allows cross origin requests? – Sidney Mar 03 '19 at 18:47
  • 1
    If you want to use this resource, you'll probably need a proxy, take a look at this service: https://cors-anywhere.herokuapp.com/ – Sidney Mar 03 '19 at 18:48
  • @pointy, Yes, that occurred to me while forming an understanding of CORS, however, it seemed like some of the documentation I found suggested modifying fetch to overcome this. Granted the circumstances in which you would be able to circumvent the policy would be limited. – Jetals Mar 03 '19 at 18:53
  • 1
    Browser plug-ins can do whatever they want, just like any other code you decide to run on your own computer. But from within the context of client-side web code, browsers enforce CORS rigidly. – Pointy Mar 03 '19 at 18:55
  • @Sidney Thanks. Yes, the data resource was provided by the company, and no, I initially didn't expect to run into such a problem with the CORS conflict, but obviously, this case suggests they are aware this conflict would need to be overcome to move on with the remaining tasks of the assessment. – Jetals Mar 03 '19 at 18:57
  • @Sidney I have encountered the cors-anywhere service as a suggestion, though wasn't sure if that were the thread to follow-through to the solution, or if there existed some more obvious, more 'built-in' solution that would have enabled me to circumvent the conflict with a simple modification to my fetch. – Jetals Mar 03 '19 at 18:58
  • Have you installed the cors module on your server side? – Webwoman Mar 03 '19 at 19:02
  • @Pointy Thank you for clarifying that. From what I've read this is absolutely the case, though I haven't gotten to a point where I've relaxed enough to fully grok the information about the CORS policy. I think my next step will be to give the suggested cors-anywhere service to create a proxy as a work-around a closer look. – Jetals Mar 03 '19 at 19:05
  • @Webwoman Thanks. My tenuous (i.e., independent, unverified) understanding of the present problem is that the page storing the JSON data is the resource, (i.e., the server side), and no, I don't have access to the server-side code, though that would be my first step if I did :-) – Jetals Mar 03 '19 at 19:08
  • 2
    `I wasn't sure if that were the thread to follow-through to the solution, or if there existed some more obvious, more 'built-in' solution` In case it's not clear, CORS is a security feature and therefore JavaScript in a web browser cannot work around it. You'll need a server to cooperate (either the original server, or a proxy) – Sidney Mar 03 '19 at 19:21
  • @Sidney Yep, I understand. Looking into the cors-anywhere documentation now. Thank you – Jetals Mar 03 '19 at 19:28

1 Answers1

1

If it's production problem - you should adjust response headers(on server side)
If it's only for development purposes(e.g. you're using webpack-devserver and trying to connect api to staging environment etc) you can:
a) get browser extensions that adjust CORS headers (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) - they change them to Access-Control-Allow-Origin: "*"
b) launch browser with appropriate start parameters(for chrome see https://peter.sh/experiments/chromium-command-line-switches/): --disable-web-security

  • ...if you use `webpack-dev-server` you can just configure it acting [as proxy](https://webpack.js.org/configuration/dev-server/#devserverproxy) for API server – skyboyer Mar 03 '19 at 22:22
  • 1
    Not always, what if you get your end point from configuration(fetched from server) and all your api requests are already: `/*` in such situation devserver proxy won't help you (and from what i can see his requests are going not to `localhost` but directly to some server) In all other situations yea, using proxy is a great solution :) – Yaroslav Stasyuk Mar 03 '19 at 22:27
  • 1
    yes, it may be harder. in such cases Fiddler helps. – skyboyer Mar 03 '19 at 22:34
  • 1
    Well, technically we can also use http-proxy and modify responses/requests to change endpoint(if it's not hardcoded on client side), but meh.. i think in that case it will be an overkill :) – Yaroslav Stasyuk Mar 03 '19 at 22:45
  • yes, completely agree – skyboyer Mar 03 '19 at 23:01
  • @YaroslavStasyuk and @skyboyer: Thank you for commenting here on my issue! I've taken some time to review the links posted in your comments and I'm definitely starting to see that the steps to turn off the policy in Chrome with `--disable-web-security` is the ticket to moving forward! – Jetals Mar 04 '19 at 13:29