I'm using an API from JIRA to get some information on bugs. Here's an example of the JQuery I'm using to get it:
var endpoint = 'https://jira.cyanogenmod.org/rest/api/latest/issue/CYAN-2631';
$.get(endpoint, function(data) {
do_stuff(data, data['fields']['project']['self']);
});
And, I'm getting the ever-terrible Access-Control-Allow-Origin error. It looks like this:
XMLHttpRequest cannot load
https://jira.cyanogenmod.org/rest/api/latest/issue/CYAN-2631.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://127.0.0.1:8000' is therefore not allowed access.
I'd really like to use this API if possible. Following the directions on this question didn't help. I got another error,
GET https://jira.cyanogenmod.org/rest/api/latest/issue/CYAN-2631callback=jQuery172039181585889309645_1431307158851?_=1431307165515
Seems to be a Jquery error, so I don't think that's the right approach. Maybe the server doesn't allow for jsonp.
Anyway, does anyone have a way around this or can I just not use this particular API? Thanks
There is no way to enable cross origin requests entirely from the browser without external code. If there was, it would entirely defeat the purpose of the security protections in the first place.
When using a browser, it is the server that decides if it wants to support cross origin requests or not and what domains it wants to support requests from. You cannot bypass it in the client.
The choices are:
Server enables CORs access from your domain or all domains.
Server supports JSONP allowing you to use it to work-around the cross origin access.
You create your own server proxy where you make a request from the browser to your own server (which would either be same origin or have CORS enabled), then your own server gets the data from the other site and returns it back to the browser. Servers are not limited by the same origin limitations as this is a security feature built into browsers only.
You find some third party proxy service that you can use to serve the same purpose as option #3.
FYI, a Google search turned up this article about enabling CORS on the API: https://answers.atlassian.com/questions/69356/cross-origin-resource-sharing-with-jira-rest-api-and-javascript. I don't understand enough about the service to quite follow the article, but maybe it points you in a helpful direction.
H-i, short answer is "yes".
The medium answer is "enable CORS on your application SERVER"
The long answer is here: http://enable-cors.org/
At some point you'll encounter the concept of a "pre-flight request", and you'll probably get confused.
That's because it's confusing, stupid, and poorly engineered. Just keep on going.
The easiest way to enable CORS is at your webserver (nginx or apache), although, you can enable it in the application itself.
The http://enable-cors.org/ site lists configurations for a variety of web servers and application stacks.
Good luck!
Related
I'm writing a small script to access an external API for work. I originally did this in Python and everything worked fine.
I was then asked to try and do it in Javascript. Now, I'm no programmer really, but I do know (or believe) that Javascript is largely for client-side, whereas PHP or Python are really for server-side operations. When I wrote the script in Python I had no problems, but in Javascript I get a
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
error. From what I've read about CORS here and similar questions on Stack, that makes sense, but I don't really understand why I don't get a similar error in Python or PHP...
I'm fairly new to this so I'm probably missing a number of things, but I'd really appreciate any insight anyone can give me. If I've left out any important info, please let me know.
From Mozilla's documentation:
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.
Since Javascript in the browser uses XMLHttpRequest and fetch to make HTTP requests, they're subject to CORS policy enforcement.
More information on the reasons for CORS:
CORS is intended to allow resource hosts (any service that makes its data available via HTTP) to restrict which websites may access that data.
Example: You are hosting a website that shows traffic data and you are using AJAX requests on your website. If SOP and CORS were not there, any other website could show your traffic data by simply AJAXing to your endpoints; anyone could easily "steal" your data and thus your users and your money.
The external API you're using likely implemented a CORS policy intentionally. For example, if the API requires an application-level secret key for authentication, a CORS policy would discourage the use of that key in a public environment (namely the browser). Alternatively, the API may have a list of acceptable domain names for CORS that doesn't include the domain you're currently using.
Those are just a few examples; there could be any number of reasons for an API to implement CORS headers.
I'd like to create a client for last.fm. My music "station" feed is here, in JSON format: http://www.last.fm/player/station/user/skeftomai/mix.
However, when I try to access this via $.getJSON(), I get
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://my.exampledomain.com' is therefore not allowed access.
So unfortunately we have a CORS issue on last.fm's end. I'd like to work around this. Here are some things I've tried:
AJAX. This fails with the Access-Control-Allow-Origin error.
An iframe with document.domain set to "www.last.fm" or "last.fm". This fails with SAMEORIGIN iframe error.
JSONP. Unfortunately JSONP doesn't seem to be supported with this feed.
A <script> tag with src pointing to the feed link. Unfortunately $('#scriptTagId').html() is empty.
Flash. But unfortunately suffers from the same cross-origin issue.
Java applet. Too heavy, everyone might not have the JVM installed, and it might suffer from the same cross-origin issue.
I'm fairly sure I could get away with a web proxy whereby the client utilizes a server-size proxy to retrieve the feed...but I really, really want this to be a pure client-side app with no server-side. I'd like to host this on a CDN (S3 + Cloudfront).
Is there ANY way around this?
No, what you are asking for isn't solvable using the browser alone. If the 3rd party site doesn't support CORS or JSONP, you're out of options unless you control the 3rd party site or can use a server of your own (or any 3rd party proxy such as YQL) to obtain the data.
Here it is with YQL:
$.getJSON('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20json%20where%20url%3D\'http%3A%2F%2Fwww.last.fm%2Fplayer%2Fstation%2Fuser%2Fskeftomai%2Fmix\'&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=?', function (response) {
console.log(response.query.results.json);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Fetch API , "successor" of AJAX seems promising, but I can't seem to find any example of cross-domain (or cross-origin if you will), and in fact, there's not much about this online except same-origin example, so does this mean JSONP is still the de-facto, straight-forward way to go in upcoming years? CORS just seems unrealistic in terms of configuration annoyance.
From the spec you linked to:
To allow sharing resources cross-origin and allow for more versatile HTTP requests than possible with HTML's form element, the platform has a CORS protocol layered on top of HTTP.
So cross-origin with fetch is handled in exactly the same way as it is handled with XMLHttpRequest.
I'm building a nodejs server and I need to access more services using ajax from another domain, so how can I break the cross-domain restriction in nodejs code?
Note: Frameworks like ExpressJS is not an acceptable solution
Generally speaking, when there is a cross domain restriction in effect you have two possible options to take.
Determine if the remote party you're trying to talk to supports CORS. Have them allow your domain on their end in the HTTP headers. Sometimes this is not possible.
Setup a reverse HTTP proxy that allows you to communicate to the remote party but goes through your web server first so you bypass the cross domain origin security issue. Node-http-proxy is a possible solution if you're already using Node.js
CORS is generally only supported in more recent browsers, so if you have a requirement to support old stuff that might not be suitable.
Note in jQuery from linked resource.
$.support.cors
boolean will be set to true if the browser supports CORS
I'm struggling at the moment with the idea of creating a cross-origin request proxy or not.
I have a jQuery application that interacts with an API, making at least 4 requests to that server on the initial page load. Both servers are completely under my control, but they are on different subdomains. For that reason, I've been heading toward the approach of using JSONP to get around the cross-origin request policies.
However, I'm really missing out on one feature in particular: getting HTTP status codes for the requests. The way JSONP + jQuery work, the request works or it doesn't. If it doesn't, I specify a timeout for the request and if that timeout is reached I assume a failure (there's no way to know otherwise). I'd really like to be able to respond to a 404 vs a 500 error from the API server.
This led me to thinking a local proxy may work better - but it would then tie up server-side resources (server that holds the jQuery application + Sinatra application) instead of client resources (the browser). That can certainly add up when each page load is 4+ requests to the API server, even though it wouldn't block the application from loading.
I understand this is not a true "question" - so feel free to flag this / close it if inappropriate. However, I'd really like to get some opinions on the subject. I'm introducing some complexity by developing a local proxy in Ruby.
I'd stick to JSONP and the direct communication between the subdomains.
Also, you might want to check out (hacky) methods of using iframes for communication. Iframes are not subject to the inter-subdomain restriction. They can communicate as long as both subdomains belong to the same top domain.
JSONP has some limitations and is not your only option. Since you control both domains have you considered using CORS? If not, check it out: http://www.html5rocks.com/en/tutorials/cors/
You can read about JSON-P vs. CORS here: http://json-p.org/