There seems to be a tonne of misguidance on this topic, mostly driven by older jQuery versions. Unfortunately this guidance seems to show up a lot in Azure + SharePoint integration conversations, so I thought, there is always time for a quick rant blog post before I board my flight (in 2 hours, and haven’t packed my bags yet!).
So, here is the deal! Things changed in jQuery 1.5, as quoted from - http://api.jquery.com/jQuery.getJSON/
As of jQuery 1.5, the success callback function receives a "jqXHR" object (in jQuery 1.4, it received the XMLHttpRequest object). However, since JSONP and cross-domain GET requests do not use XHR, in those cases the jqXHR and textStatus parameters passed to the success callback are undefined.
Another issue of course is, such cross-domain requests are inherently insecure. Either you are sending credentials over clear text, OR, you cannot make cross-domain requests (not without an ugly client side warning atleast) on HTTPS.
So how do we make cross-domain requests work with jQuery? Now, as you know, $.get and $.getJSON use $.ajax. Since jQuery 1.5, there has been a new property added to $.ajax. It’s called ‘crossDomain’.
crossDomain:
Default: false for same-domain requests, true for cross-domain requests
If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain.
Source: http://api.jquery.com/jQuery.ajax/.
The server side redirection is quite simple to do in PHP, as shown below,
1: $data = '{"name" : "hello world"}';
2: echo $_GET['jsoncallback'] . '(' . $data . ');';
You can also use YQL (Yahoo Query Language) to perform such server side redirection as shown below,
1: jQuery.ajax = (function (_ajax) {
2: var protocol = location.protocol,
3: hostname = location.hostname,
4: exRegex = RegExp(protocol + '//' + hostname),
5: YQL = 'http' + (/^https/.test(protocol) ? 's' : '') + '://query.yahooapis.com/v1/public/yql?callback=?',
6: query = 'select * from html where url="{URL}" and xpath="*"';
7:
8: function isExternal(url) {
9: return !exRegex.test(url) && /:\/\//.test(url);
10: }
11:
12: return function (o) {
13: var url = o.url;
14: if (/get/i.test(o.type) && !/json/i.test(o.dataType) && isExternal(url)) {
15: o.url = YQL;
16: o.dataType = 'json';
17:
18: o.data = {
19: q: query.replace(
20: '{URL}',
21: url + (o.data ?
22: (/\?/.test(url) ? '&' : '?') + jQuery.param(o.data)
23: : '')
24: ),
25: format: 'xml'
26: };
27: if (!o.success && o.complete) {
28: o.success = o.complete;
29: delete o.complete;
30: }
31:
32: o.success = (function (_success) {
33: return function (data) {
34: if (_success) {
35: _success.call(this, {
36: responseText: data.results[0]
37: .replace(/<script[^>]+?\/>|<script(.|\s)*?\/script>/gi, '')
38: }, 'success');
39: }
40: };
41: })(o.success);
42: }
43: return _ajax.apply(this, arguments);
44: };
45: })(jQuery.ajax);
46:
47: function InitializeWebPart() {
48: $.get('https://someotherURLCrossDomain', function (data) {
49: $("#results").html(data.responseText);
50: });
51: }
Writing a web role in Azure to do server side redirection is also quite trivial.
Few other notable points about cross domain ajax requests using jQuery -
- The error handler won’t get called on such requests. $.ajaxSend and $.ajaxError cannot be used with such requests.
- You can secure such requests by using xhrFields { withCredentials: true }
- You cannot make such requests synchronously.
- Get requests are a matter of making a simple call. PUT/POST/DELETE/MERGE verbs need an additional handling especially for security. There is an ‘OPTIONS’ verb sent before those other verbs can be called.
Gotta run!