1

I know that title of this question makes no sense, because client does not share anything, it requests. But, say I want to write a RSS reader as an excercise. So I would store all my data on client in IndexedDB (or localstorage), and I want to fetch some streams. So I do for example

fetch('https://bunyk.wordpress.com/feed/')

But wordpress.com is not in my controll, and it gives me error

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

I could avoid that error by using {mode: 'no-cors'}, but in that way I'm not able to get contents too.

Is there any way to make it work, or I need to write and host some thin backend that proxies that requests and adds 'Access-Control-Allow-Origin' header? (Probably such proxy already exists somewhere?) Or could I use something from Progressive Web Apps abilities, like Service Workers? Or should I use something like Electron or Cordova? What I wish to do, is to make my app work on mobile too.

Bunyk
  • 7,635
  • 8
  • 47
  • 79
  • you need to check if the wp site you are trying to connect to supports jsonp in communications. – Vladimir M May 12 '17 at 08:37
  • @VladimirM Not likely. :( – Bunyk May 12 '17 at 08:51
  • Possible duplicate of ["No 'Access-Control-Allow-Origin' header is present on the requested resource"](http://stackoverflow.com/questions/20035101/no-access-control-allow-origin-header-is-present-on-the-requested-resource) – Liam May 12 '17 at 08:52
  • @Liam I believe I can. For example python fetch data from that request easily. It just don't sends 'Origin' request header, and does not implement http access control at all. So, I'm trying here to find out if there is a way to switch a browser in mode which allows this. Maybe by writing this as browser extension? – Bunyk May 12 '17 at 08:58
  • Python is not javascript. It does not implement CORS restrictions – Liam May 12 '17 at 08:59
  • Basically read this https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS – Liam May 12 '17 at 08:59
  • @Liam NodeJS is javascript but it does not implement CORS restrictions too. Browsers do. But even chrome has `--disable-web-security` flag. And probably there are other ways, like writing some proper manifest.json – Bunyk May 12 '17 at 09:02
  • @Bunyk — No. A website cannot use a manifest file in order to access data on a different website using the owner of the browser's identity. – Quentin May 12 '17 at 09:03

3 Answers3

2

How to do Cross-Origin Resource sharing from client?

You can't. It would make having the permissions security pointless if your code could grant itself permission to access anything it liked.

some thin backend that proxies that requests and adds 'Access-Control-Allow-Origin' header?

It only needs to add the header if the proxy itself is cross-origin, but yes: That is the standard approach to getting around the SOP for publically available data when you don't have the cooperation of the host.

Probably such proxy already exists somewhere

There are many. I won't recommend any particular one.

Or could I use something from Progressive Web Apps abilities, like Service Workers?

No

Or should I use something like Electron or Cordova?

If you're doing that then you would be writing software that the user would have to explicitly install. It wouldn't be a web app. The SOP wouldn't apply (at least not in the usual way).

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
2

You can right now do this:

fetch('https://cors-anywhere.herokuapp.com/https://bunyk.wordpress.com/feed/')

…and it will just work.

That causes the request to be made to https://cors-anywhere.herokuapp.com, a open/public proxy which will then send it to https://bunyk.wordpress.com/feed/. And when that proxy gets the response, it’ll take it and add the Access-Control-Allow-Origin response header to it and then pass that back to your requesting frontend code as the response.

That response with the Access-Control-Allow-Origin response header is what the browser sees, so the error message the browser engine is showing you now goes away, and the browser allows your frontend JavaScript code to access the response.

Or use the code from https://github.com/Rob--W/cors-anywhere/ or such to set up your own proxy.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • Yes! `fetch('https://cors-anywhere.herokuapp.com/https://bunyk.wordpress.com/feed/').then(r => r.text()).then(console.log.bind(console))` just gives me my feed right here on SO. :) – Bunyk May 12 '17 at 09:11
  • This feels like a security flaw that will get patched one day? – Liam May 12 '17 at 09:46
  • 2
    @Liam See https://stackoverflow.com/questions/43154170/is-it-safe-to-enable-cors-to-for-a-public-and-readonly-webservice/43154277#43154277. For any resource already accessible from a simple `curl` request or whatever & not behind an intranet/firewall, it’s safe to send an `Access-Control-Allow-Origin: *` header for all responses. So the flaw’s arguably that most sites aren’t yet just configured by default to do that—to send an `Access-Control-Allow-Origin: *` header. If they were, it’d obviate the need to use proxies, & make life easier for web devs who want to work with them programatically. – sideshowbarker May 12 '17 at 09:58
-3

This is my opinion and may be what you require or otherwise. Setting up proxy can be a real pain and jsonp seems cumbersome to me.

u can write ur own function (for cors). Start with using XMLHttpRequest2 (firefox, etc) and XDomainRequest for IE.

Something like this:-

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {

    // Check if the XMLHttpRequest object has a "withCredentials" property.
    // "withCredentials" only exists on XMLHTTPRequest2 objects.
    xhr.open(method, url, true);

  } else if (typeof XDomainRequest != "undefined") {

    // Otherwise, check if XDomainRequest.
    // XDomainRequest only exists in IE, and is IE's way of making CORS requests.
    xhr = new XDomainRequest();
    xhr.open(method, url);

  } else {

    // Otherwise, CORS is not supported by the browser.
    xhr = null;

  }
  return xhr;
}

var xhr = createCORSRequest('GET', url);
if (!xhr) {
  throw new Error('CORS not supported');
}

Reference:- https://www.html5rocks.com/en/tutorials/cors/

Shows how u can do headers, etc. (scroll to "Handling a not-so-simple request") May be helpful to you or otherwise. Hope this helps .

Plankton
  • 388
  • 3
  • 13
  • This won't make any different, if the server doesn't send back a `Access-Control-Allow-Origin` header, no changes to the Js will make any difference – Liam May 12 '17 at 09:00
  • 1
    The question is asking about making a request to a server that doesn't grant permission with CORS. It isn't asking how to access a server which *does* grant permission using an obsolete and unsupported version of Internet Explorer. – Quentin May 12 '17 at 09:00
  • XHR was rewritten in terms of fetch, so this answer is outdated – Robert Mennell May 12 '17 at 20:00