First of all, let’s try to be precise here: when we speak about “domain” we are only saying part of the truth. The focal point is indeed the origin. Not only the hostname must match but also the protocol and the port. This is why there will be no joy between
http://example.com:3000/ and not even between
http://example.com. No way to touch
Why?, you ask squinting. It’s all about security. It’s for your own good. Trust them.
Let’s briefly discuss which are the most common options you have to overcome this limitation.
- Cross-origin resource sharing (you’ll always use the much cooler CORS acronym for that). CORS is nothing more than the good old XMLHttpRequest, with an additional HTTP header:
Access-Control-Allow-Origin sent by the server (or the application). With that header the server is telling the browser that he’d permit requests from whoever matches the value of that header (with an “*” meaning “everyone is welcome”). CORS is nice and simple, but you need control over the server (to send the header) and support from the browser (to apply the policy, parsing the new header). Needless to say, the problem with browsers is Internet Explorer: we can use CORS only with IE8 onward - and it also needs a special treatment. You might want to take a look at the advocating site for CORS for more details
crossdomain.xml. The file contains instructions to white-list which domains can access the resources from the server; more on this on Brightcove. Admittedly, this solution is fairly good: it’s cross browser, robust and Flash is - so far - widely available, but you still need control over the server (deploying the crossdomain.xml file). You should also probably want to use a ready to use library: I could suggest you flXHR, if only the project would still be actively maintained. Please note that there is another fairly important limitation: as far as I know, you cannot issue synchronous HTTP requests with Flash.
SCRIPT tag in the browser. The
JSONP suffers of a big limitation, though. First of all, just focus on these points:
- JSONP is not properly Ajax. At least, it doesn’t use XMLHttpRequest at all
- JSONP will always use an asynchronous HTTP GET
- JSONP relies completely on how the browser (not your code) fetches the script from the server. There is no “standard” way, on this. I could write a browser that will not fire the “onload” event after a successful load of the script and you’ll be screwed (the callback will not be called)
The last point is the most important one: a corollary to it is that error management with JSONP is a problem. You’d like to get fine control over errors that could eventually arise trying to fetch important data from the server. With XMLHttpRequest this is a solved problem: you have the fine “error callback” that every library will give you for free… any HTTP status code that is not 200 will fire the callback and you’re safe: you access the error object with all the data you need to understand what is going on.
That’s not the case with JSONP. Let’s dig deeper into this mess, using the jQuery JSONP implementation:
- Same domain, HTTP Status 404 the request will be converted to a normal XHR call, so the error is raised and you get the full XHR object to play with
- Same domain, HTTP Status 500 the request will be converted to a normal XHR call, so the error is raised and you get the full XHR object to play with
- Cross domain, HTTP Status 404 the request fails silently in every browser (the error callback is not even called).
- Cross domain, HTTP Status 401, 403 the request fails silently in every browser EXCEPT Chrome. In Chrome the error callback is called with the parsererror error
- Cross domain, HTTP Status 500 the request fails silently in every browser EXCEPT Chrome. In Chrome the error callback is called with the parsererror error
- Cross domain, HTTP Status 200, bad JSON error callback is fired in every browser (additionally, a JS error is raised). Status is 200 and error is “parsererror”
This report is only partial, not accurate and it will possibly change in time, but the message is clear: if you need fine errors control over the communication, you just don’t want to use JSONP.
The long term solutions for cross domain communication are then CORS (solid, standard, future proof) or some kind of tecni que stack involving cross domain messaging using HTML5 postMessage and XMLHttpRequest (using an hidden iframe and some juggling).
But cross domain messaging is another big topic that surely deserves a post for its own.