Cross-origin resource sharing for API access in JavaScript

(Nicolas_Blanco) #1


I am trying to develop a JavaScript plugin to retrieve the latest topics of my Discourse instance and display them dynamically in the user’s browser.

I am using AngularJS to do this.

Unfortunately, CORS (Cross-origin resource sharing) is not supported in Discourse (or I didn’t see a configuration option :smile:).

Temporarily, I’ve added the gem rack-cors (GitHub - cyu/rack-cors: Rack Middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.) to my Discourse instance, and added the middleware. It works perfectly and I was able to request the Discourse API from my external website.

Would you accept a pull request adding this gem and maybe some configuration settings for it ?



What are the risks of enabling Cross-origin resource sharing (DISCOURSE_ENABLE_CORS)
(Sam Saffron) #2

I wonder if we should provide a JSONP api to avoid needing this. I am ok to support this optionally, default off.

I would not include a site setting cause this needs to be wired up on startup and is not a per site thing really. See the implementation of Rack Cache for an example of how to add this.

(Nicolas_Blanco) #3

I thought that JSONP should be deprecated in favor of CORS which is implemented in every browser since IE 8…

I understand that it cannot be a site settings because it is configured on startup. I’ll do a pull request later, thanks :wink:

(Benjamin Kampmann) #4

Having had this problem myself when trying to integrate discourse content into third party webservices, I added support for configuring the ‘Access-Control-Allow-Origin’. You can find the pull request here. Enjoy.

(Jeff Atwood) #5

CORS is kind of problematic, for example:

The reality is that CORS still causes problems, even with modern browsers. The biggest problem we have found was with some firewalls/proxies that refuse HTTP OPTIONS queries. We even found softwares on some computers that were blocking CORS requests, as the Cisco AnyConnect VPN client, which is widely used in the enterprise world. We have found this issue when a TechCrunch employee was not able to operate search on because the AnyConnect VPN client was installed on his laptop.

So in conclusion it is not possible to have a perfect service quality with a CORS-enabled REST API, even in 2014 with the big majority of the browsers supporting CORS!

(Mark Nutter) #6

I ran across that same article today but I’m not as pessimistic as the author is. I reached out to Cisco for an answer but also ran across this thread: that talks about a similar issue that Cisco fixed. So perhaps the version of AnyConnect they were using is out of date. We just don’t know enough about the pervasiveness of this issue to declare CORS unusable.

(Anton) #7

At the end, did we get JSONP available?
I’m testing a widget that fetches latest topics, by default from Discourse Meta.
It does not allow me to make a “jsonp” requst, nor it provides a CORS header for anonymous users.

(Blake Erickson) #8

You could write some code on the server that is hosting your domain that talks to the Discourse API and then your js could talk to your own server and not have to worry about jsonp or CORS.

Or spin up a tiny heroku app that’s does the same thing and enable CORS there.

(Anton) #9

Yes this is a workaround, but my goal is to develop a JS widget that can read from a Discourse instance without need to supply additional server-side scripts. Thats why I’m asking about JSOP.

It looks though that for the ones who’ll use the widget it will be necessary to enable cross-origin header and rebuild their Discourse, as well as add the requester domain.

(elle) #10

although this might let this topic drift into another direction, I wonder:

How can we use a User API Key using JavaScript embedded in a different domain than the discourse site is on?

I can get the API calls to work with a regular api key, however, due to these being read/write I’d rather use User API Keys with only read access. I think this is currently not possible since the needed headers USER_API_KEY and USER_API_CLIENT_ID are not allowed CORS headers, as seen here: discourse/008-rack-cors.rb at master · discourse/discourse · GitHub