Performing cross-domain Ajax requests, Five JavaScript Tips in Five Days

Sometimes it's necessary to perform a cross-domain Ajax request, despite that the standard doesn't allow it. There are several ways of working around this restriction. In this post, I talk about the options, along with which you should be using (the answer shouldn't surprise you).

XMLHttpRequests have a built-in security measure denying requests made across domains. For example, a page served from www.example.com cannot make a request of a page found at www.example.org. This is nice, simple security, but is sometimes a hurdle to be overcome, such as if you wanted to dynamically make use of Google, Amazon, or Yahoo services on your site.

Instead of writing one of those articles that discusses all the ways you could do something and then concludes with how you really should do it, I'm doing the discussion in reverse.

The simplest and most obvious way to circumvent the cross-domain request restriction is to use what's called a cross-domain, or application, proxy. This is just a server-side script on your domain that performs the request from the other domain and then returns the result.

For example, your page on www.example.com might call a PHP script also on www.example.com. That PHP script makes the request from www.example.org (because there is no inherent restriction in doing so), reads in the response, and returns it to the original page. Besides being effective, this method also allows you to use PHP (or whatever server-side technology) to validate the returned data, store it in a database, log the transaction, whatever.

The code involved is really rather simple. Despite that, I can't include any here because there are so many different services out there, but the premise is just:

An Ajax request is made of your server-side script, passing any necessary parameters along in the URL.

The server-side script makes the request of the destination server. For security purposes, the destination should be a hard-coded URL, so that your server-side script doesn't turn into an open proxy for the entire Internet.

The server-side script reads in the response, validates it, and so on.

The server-side script echos out the response as valid XML, JSON, or plain text.

The JavaScript in the client handles the response as if it was coming from the same server. Which, in fact, it is.

So, to be absolutely clear, using an application proxy really is the way to go. It's comparatively secure and can be made even more so using the server-side technology; it requires no cooperation from the remote server (more on this soon); and requires no other configuration of your server or additional browser support. Now, technology is often about people thinking they can build a better mousetrap, so some of the alternatives are...

The Flash Bridge
The same concept of using an agent to perform the request can be accomplished using client-side Flash. But this does require that the browser have the Flash plug-in installed (not a big restriction) and, more important, assumes that the remote server has a proper cross-domain policy file in place. This is a special XML file that dictates who can access what content from outside domains. I'm of the opinion that if you're going to use JavaScript to call upon Flash, you might as well use all Flash and drop the JavaScript, but maybe that's just me.

Cross-Domain JSON
Another commonly mentioned way of performing a cross-domain request is to use cross-domain JSON, also called On-Demand JavaScript. It works like so:

HTML SCRIPT tags can contain only JavaScript.

JSON is not just a data format, it's also pure JavaScript.

So if a file on another domain returns JSON, it can be used as the source in a SCRIPT tag as if it were any normal JavaScript file.

As with the cross-domain policy files and Flash, this process does require that the remote server be set up to allow for this type of communication (some, such as Yahoo, are). In particular, the remote server needs to be passed a reference to a callback function (defined in your JavaScript code) that will be called when the JSON data is returned from the remote server. So this isn't always possible.

Also, there's the huge security issue involved in using JSON, particular JSON from 3rd parties (see my other blog post or search the Web for more). But in this case, you're not just using remote JSON, you're using remote JavaScript. In other words, you're running someone else's JavaScript on your page. This means, for example, the remote JavaScript will be able to review the Document Object Model of the original HTML page (your HTML page) and do whatever it wants with it. This is a cool trick, yes, but an unnecessary risk as far as I'm concerned.

And More!
There are even other options beyond those two (which are the primary alternatives to a cross-domain proxy). A search online will return a discussion of Apache modifications that can be used to work around the cross-domain requests using mod_proxy and/or mod_rewrite. But, of course, you'd need the ability to modify how your Web server runs (not something everyone has) and, do you really want to alter Apache's behavior just so you don't have to use a server-side application proxy?

Another option is to use iFrames. Although there are restrictions in communications between iFrames (or an iFrame and the main page), through URL manipulations some communication can be achieved. Still, there's limited usefulness here as a way of transmitting data and, again, there are security concerns.

It's great that there are multiple ways to do things and that smart people are striving for better options. But a new mousetrap isn't always a better one and, in some cases, may actually be worse. I'm sure plenty of people out there have a different opinion on this issue (and please offer them up in comments), but as far as I'm concerned, learn how to use a server-side proxy and forget about these others. Your dynamic Web site will work and you'll sleep better knowing you haven't circumvented one security policy by introducing new holes.

For more on related topics, please check out my books. And be sure to check back here each day this week for more JavaScript tips.