Cross Domain Ajax Calls

Here are a few of the most popular ways to do cross domain calls via JavaScript: proxies, JSON, and Flash.

Cross domain proxy

This is one of the most common approaches. Your script calls your server, your server makes the call to the remote server and then returns the result back to the client. There are some definite advantages to this approach: you have more control over the entire lifecycle. You can parse the data from the remote server, do with it what you will before sending it back to the client. If anything fails along the way, you can handle it in your own way. And lastly, you can log all remote calls. WIth that you can track success, failure and popularity.

Cross domain JSON

For this to work, the remote server needs to be set up to handle this. It needs to accept an additional parameter: a callback function. Then, to make the remote request, you insert a new script tag into your page with which will allow you to specify a remote URL. The reponse back will load a JSON object as a parameter of the callback function you specified in the request. Yahoo, for example, has implemented this feature in their web services API’s. This is great because you can implement web service calls without ever needing a scripting language on your server. Check out Jason Levitt’s article, JSON and the Dynamic Script Tag, on XML.com for more information.

Cross domain using Flash

Flash, by default, is much like Ajax in that you cannot request data from a remote server. However, you can enable this capability by placing a special XML file on the remote server to accept requests from other domains. With JavaScript’s capability to interact with Flash, we can use Flash as a bridge for sending cross-domain requests. (XML.com has a nice write-up of this technique.) There are still some limitations to this technique, most of which seems to be limited to older versions of Flash. There’s also the issue with users having Flash installed and enabled.

Sub-domains are still cross domains

One point to note and it’s fairly subtle. Plenty of us have our sites running at www.example.com and at example.com. They both point to the very same place. To us, we see them as the same thing. But to an Ajax call, it’s considered cross domain. Therefore, if you have to make an Ajax call to the same server, don’t code the domain as part of the request; just use the path.

The Future

Some have already begun looking into establishing standards that could be implemented into future browsers, such as JSONRequest and ContextAgnosticXMLHttpRequest. JSONRequest seems the most promising but that could be because I prefer JSON over XML and see it as really gaining traction over the next couple years.

Cross Domain Ajax Calls

When Microsoft added the ActiveX XMLHTTP object to Internet Explorer’s implementation of JavaScript, the company planted the seed for the revolution in Web applications known as Asynchronous JavaScript and XML, or AJAX. Today, Firefox, Safari, Opera, and other browsers all support what is now known as XMLHttpRequest, making possible sites such as colr.org, backpackit.com, and maps.google.com. These and other sites feature applications that act and feel like other desktop applications—even though they’re running in a browser.

In AJAX, the JavaScript on the page sends requests to a Web server for data while the user’s viewing and interacting with the page (hence the "asynchronous" part of AJAX). Those requests are HTTP requests just like the one the browser used to retrieve the page in the first place, as well as any images, stylesheets, and so forth. As such, the XMLHttpRequest object can be used to retrieve any kind of data, not just XML. For example, JavaScript can use XMLHttpRequest to retrieve a plain text file from a Web server and display its contents within a form.

The XMLHttpRequest object analyzes the MIME type of the data coming back from the Web server by looking at the Content-type header that precedes the data. If it’s text/plain for example, you can access the text by examining the XMLHttpRequest object’s responseText property. But, if it’s text/xml, the XMLHttpRequest object takes an extra step: It runs an XML parser on the returned document and builds a Document Object Model (DOM) tree in memory representing the document, and makes that available in the responseXML property. You then can use JavaScript’s standard DOM methods to navigate the tree and retrieve elements, attributes, and other text occurring in the tree.

XML is the standard way to interchange data, but it’s often not the best way. Although XML can add structure and metadata to data, it does so in an overly verbose way. XML also has a fairly complex syntax, requiring a non-trivial parser to attack it. In JavaScript, XML must be parsed into a DOM tree to be used. And, once you’ve constructed the DOM tree, you still have to pilot through it to create corresponding JavaScript objects or otherwise use the XML data in your client-side Web application.

Fortunately, there’s a better way.

Welcome to JSON

The JavaScript Object Notation, or JSON, is a lightweight syntax for representing data. JSON’s elegance comes from the fact that it’s a subset of the JavaScript language itself. You’ll see why that’s important later. First, compare the raw syntax of JSON against XML.

Both XML and JSON use structured approaches to mark up data. For example, an address book application might provide a Web service that yields address cards in this XML format:

<?xml version='1.0' encoding='UTF-8'?><card>   <fullname>Sean Kelly</fullname>   <org>SK Consulting</org>   <emailaddrs>      <address type=’work’>kelly@seankelly.biz</address>      <address type=’home’ pref=’1′>kelly@seankelly.tv</address>   </emailaddrs>   <telephones>      <tel type=’work’ pref=’1′>+1 214 555 1212</tel>      <tel type=’fax’>+1 214 555 1213</tel>      <tel type=’mobile’>+1 214 555 1214</tel>   </telephones>   <addresses>      <address type=’work’ format=’us’>1234 Main St         Springfield, TX 78080-1216</address>      <address type=’home’ format=’us’>5678 Main St         Springfield, TX 78080-1316</address>   </addresses>   <urls>      <address type=’work’>http://seankelly.biz/</address>      <address type=’home’>http://seankelly.tv/</address>   </urls></card>

With JSON, it looks like this:

{   "fullname": "Sean Kelly",   "org": "SK Consulting",   "emailaddrs": [      {"type": "work", "value": "kelly@seankelly.biz"},      {"type": "home", "pref": 1, "value": "kelly@seankelly.tv"}   ],    "telephones": [      {"type": "work", "pref": 1, "value": "+1 214 555 1212"},      {"type": "fax", "value": "+1 214 555 1213"},      {"type": "mobile", "value": "+1 214 555 1214"}   ],   "addresses": [      {"type": "work", "format": "us",       "value": "1234 Main StnSpringfield, TX 78080-1216"},      {"type": "home", "format": "us",       "value": "5678 Main StnSpringfield, TX 78080-1316"}   ],    "urls": [      {"type": "work", "value": "http://seankelly.biz/"},      {"type": "home", "value": "http://seankelly.tv/"}   ]}

As you can see, JSON has structure with nesting of data elements, just as XML does. JSON too is text-based, as XML is. Both use Unicode. JSON is just as readable by humans as XML is. Subjectively, JSON is clearer and has less redundancy. The JSON Web site describes the syntax of JSON rigorously, and yet does so briefly. It really is a simple little language! XML is certainly appropriate for marking up documents, but JSON is ideal for data interchange. Each instance of a JSON document describes one object with nested objects, arrays, strings, numbers, boolean values, or null values.

In these address card examples, the JSON version is lighter weight, taking 682 bytes of space, whereas the XML version requires 744. That’s not a spectacular savings, of course. The real benefits come in the parsing.

XML Versus JSON: the Smackdown!

By using the XMLHttpRequest object, you can retrieve both XML and JSON files from within your AJAX-based application. Typically, your interaction will go something like this:

var req = new XMLHttpRequest();req.open("GET", "http://localhost/addr?cardID=32", /*async*/true);req.onreadystatechange = myHandler;req.send(/*no params*/null);

As the Web server replies, the handler function you passed in (myHandler in this example) is called repeatedly, affording you an opportunity to abort the transaction early, update a progress bar, and so forth. Frequently, you only take action when the Web request is complete; at that time, you use the returned data.

To handle the XML version of your address card, the code for myHandler might look something like this:

function myHandler() {   if (req.readyState == 4 /*complete*/) {       // Update address field in a form with first street address       var addrField   = document.getElementById(’addr’);       var root        = req.responseXML;       var addrsElem   = root.getElementsByTagName(’addresses’)[0];       var firstAddr   = addrsElem.getElementsByTagName(’address’)[0];       var addrText    = fistAddr.firstChild;       var addrValue   = addrText.nodeValue;       addrField.value = addrValue;   }}

Notice that you didn’t have to parse the XML document; the XMLHttpRequest object did that automatically and made the parsed DOM tree available in the responseXML property. By using that property, you call the getElementsByTagName method to find the addresses part of the document, and you use the first one (of only one) found. Then, you call getElementsByTagName again this time on that addresses element to find the first address element, and again use the first one found. Then, you get the first DOM child of that element, which is a text node, and get the node’s value, which is the street address you want. Finally, you can display it in the form field.

That’s a lot of work! Now, let’s try it with JSON:

function myHandler() {   if (req.readyState == 4 /*complete*/) {       var addrField = document.getElementById(’addr’);       var card = eval(’(’ + req.responseText + ‘)’);       addrField.value = card.addresses[0].value;   }}

The first thing you need to do is manually parse the JSON response. However, because JSON is a subset of JavaScript, you can use JavaScript’s own compiler to do just that by calling eval. Parsing JSON is a one-liner! Moreover, navigating an object synthesized from JSON is identical to navigating any JavaScript object. It’s far easier than navigating through the DOM tree. For example:

  • card.addresses[0].value is the first street address, "1234 Main Stb &"
  • card.addresses[0].type is the type of the address, "work"
  • card.addresses[1] is an object which is the home address
  • card.fullname is the name on the card, "Sean Kelly"

If you’re watching closely, you might’ve noticed that the XML version at least states up front what object is contained in the document with the root document element, card. This is absent in the JSON version. Why? Presumably, if you’re developing JavaScript that accesses a Web service, you already know what you’re going to get back. However, you can include such a nicety in JSON:

{"card": {"fullname": ...}}

By using this technique, your JSON files always start with an object with a single named property that identifies the "kind" of the object.