Blog

Cross Domain Scripting with jQuery and flXHR

We were recently asked to develop some javascript widgets that would read from a central REST based API. And of course, these widgets needed to be able to be put on any website. That’s all well and good until Cross Site Scripting rears it’s ugly head. As of right now, modern browser don’t allow AJAX calls to be made from one domain to another. There are a lot of potential security problems with cross domain scripting, though they’re not really my concern. For the purposes of this article, I’m only concerned with how we can work around these browser restrictions.

Luckily there are a few options. The first of which is to use JSONP. If you’re not familiar with JSONP, you can get caught up here. The problem with JSONP is that it only works for GET requests. In simple situations, that will probably suffice. But in more complex situations, where you might need to use POST, PUT, or DELETE, another solution is going to be needed. But more about that later… Back to JSONP. jQuery has a pretty simple JSONP implementation. Let’s take a look at a regular jQuery JSON GET request.

 
$.getJSON("test.js", function(json) {
    alert("JSON Data: " + json);
});

Nothing too out of the ordinary there. It makes a request to test.js and the callback function receives the results of the request as a json object. Suppose that test.js is now a different domain than the script that is calling it. This is when you need to use JSONP. With jQuery, making a JSONP request is quite easy. All you need to do is append a query string argument called jsoncallback, that is the name of the function that’s used as your JSONP wrapper. Let’s look at an example:

 
$.getJSON("http://someotherdomain.ca/test.js?jsoncallback=myFunction", function(json) {
    alert("JSON Data: " + json);
});

and where the GET request to http://someotherdomain.ca/test.js returns something like this:

 
myFunction({data: 'value'});

The trick with JSONP is that the server that you’re making the GET request to, has to be returning the JSON in a wrapper function and you need to know the name of that function. Alternatively, jQuery allows you to not specify the name of the callback function and use a ? as a placeholder instead. jQuery will then generate a unique callback function name and pass that as a parameter in the GET request.

 
$.getJSON("http://someotherdomain.ca/test.js?jsoncallback=?", function(json) {
    alert("JSON Data: " + json);
});

What gets sent to the server looks something like this: http://someotherdomain.ca/test.js?jsoncallback=12049583_dss. The code running on the someotherdomain.ca server will need to check that the jsoncallback query parameter exists and then return a response like:

 
12049583_dss({data: 'value'});

This can get tricky if you’re not in control of the code that you’re making requests to. JSONP isn’t a solution for all situations; it really only covers a subset of use cases for cross domain scripting. If you find that you’re unable to utilize JSONP, you may need to move to a more robust solution.

Enter flash proxies. Flash can make cross domain requests. All that’s required is that the server that you’re calling as a file in it’s root directory called crossdomain.xml. It will look something like this:

 
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<!-- Policy file for xmlsocket://socks.mysite.com -->
<cross-domain-policy>
   <site-control permitted-cross-domain-policies="master-only" />
   <allow-access-from domain="*" />
   <allow-http-request-headers-from domain="*" headers="*" />
</cross-domain-policy>

The crossdomain.xml is a pretty powerful little file and care needs to be taken when using it. Now that the server can accept cross domain requests, we need to find the right flash proxy to make those requests. The best one that I could find is called flXHR. flXHR only requires the inclusion of a javascript file, then uses javascript to write a hidden swf to the dom, and then uses that swf to make the cross domain requests. It has an API identical to the XmlHttpRequest object, so if you’re comfortable working with the XmlHttpRequest object, you’ll already be comfortable working with flXHR. Plus, flXHR offers plugins for most of the major javascript frameworks. Since we were already using jQuery, let’s take a look at an example of using flXHR with jQuery.

First we include all the files we need:

 
<!-- include the flXHR file -->
<script type="text/javascript" src="flXHR.js"></script>
 
<!-- include the most recent version of jQuery -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
 
<!-- include an xhr jquery plugin, used from the flXHR jquery plugin -->
<script type="text/javascript" src="jquery.xhr.js"></script>
 
<!-- include the flXHR jquery plugin -->
<script type="text/javascript" src="jquery.flXHRproxy.js"></script>

Then let’s write the javascript to make the requests:

 
$(document).ready(function()  {
 
	// set up the domain that we're going to call and tell flXHR not to try to parse the response as XML..
	$.flXHRproxy.registerOptions("http://someotherdomain.ca/", {xmlResponseText:false});
 
	// set flXHR as the default XHR object used in jQuery AJAX requests
	$.ajaxSetup({transport:'flXHRproxy'});
 
	// make a post request
	$.post(
		"http://someotherdomain.ca/some-process.php",
		{param1: 'abc', param2: 'xyz'},
		function(json) {
			alert("JSON Data: " + json);
		},
		'json'
	);
 
});

And that’s about it! Now you’ll be able to make cross domain POST requests.

11 Responses to Cross Domain Scripting with jQuery and flXHR

  1. Les Kendall says:

    I was looking for something like this. Our Cyberforth Room Booking System uses public and private databases on different domains. It will be interesting to try this bit of jQuery.

  2. Hi. Is this a problem for every browser, or is it only one? Just curious. I use both Firefox, Opera and Chrome. I think Opera is the most stable one, but firefox comes with a lot of add-ons that are useful, and chrome I just use for testing. – Ray. J.

  3. trykksaker says:

    Great work. I am just curious if you get it to work on every website format?=

  4. This is exactly what i was looking for, going to help me a lot with a current project. Does this work in all browsers?

  5. since it’s all jQuery based, it will work in all of the browsers that jQuery supports. you can find out which browsers here:
    http://docs.jquery.com/Browser_Compatibility

    for the flXHR it will work in all browsers that have flash installed (within the subset of browsers that are supported by jQuery)

  6. Manoj Singh says:

    Hi Guys,

    Thanks for great post!

    I have implemented it to my project, all is working fine till I am using the same domain for example if my login page is (http://staging/login/loginpopup.aspx) and its sending the request to (http://staging/login/login.aspx) for user authentication it works great, just when I change it for HTTPS request, I mean when I send to HTTPS request (https://staging/login/login.aspx) from HTTP it is giving error “text/html (NS_ERROR_PROXY_CONNECTION_REFUSED)” in firefox and “Access Denied” error in IE7 and IE8.

    Please suggest what I am missing or what changes are required to fix it.

  7. Manoj says:

    Hi,

    Thanks for great post!

    I have implemented it to my project, all is working fine till I am using the same domain for example if my login page is (http://staging/login/loginpopup.aspx) and its sending the request to (http://staging/login/login.aspx) for user authentication it works great, just when I change it for HTTPS request, I mean when I send to HTTPS request (https://staging/login/login.aspx) from HTTP it is giving error “text/html (NS_ERROR_PROXY_CONNECTION_REFUSED)” in firefox and “Access Denied” error in IE7 and IE8.

    Please suggest what I am missing or what changes are required to fix it.

  8. Pet Dood says:

    Thanks for the article. I have been wrestling with this for days now, but your solution uses a swf file as a work around. We are developing a mobile app with jqtouch/jquery which posts data from the app to the mobile server which is causing all sorts of cross domain headaches. I’m guessing with your solution we will be dead in the water on iphone since it doesn’t run flash?

    Thanks

  9. Jeune gay says:

    Good work thanks for this sharing !!!!!!

  10. Great! Thanks everybody:-) Really nice of you all.

*
To prove that you're not a bot, enter this code
Anti-Spam Image