Swiss army knife

Here at AIS, we’ve found Windows Azure Blob Storage to be an inexpensive, fast hosting solution for non-text or server-side loaded resources. But what if we want to use client-side JavaScript to load HTML fragments or JSON data directly from blobs? Under normal circumstances this is prevented by JavaScript’s Same Origin Policy; that is, you can’t load HTML fragments or JSON from another domain, subdomain, port or protocol.

One commonly used solution to this restriction is JSONP, but this is not available with Azure Blob Storage. Another modern option is Cross-Origin Resource Sharing (CORS), but it is also unavailable on Azure Blob Storage and not supported in some legacy browsers.

We could consider a server-side solution, such as employing an Azure Web Role to read text-based content from blob storage and serve it up from the original server. But this approach can be both wasteful and performance inhibiting.

easyXDM to the Rescue

The easyXDM library provides a lightweight, easy-to-use solution to this problem. It employs the “hidden iframe” technique to facilitate cross-domain calls and provides a transport stack for communication between the main window and the iframe.

In modern browsers easyXDM uses the HTML5 postMessage() API as the communication transport between the main document and iframe; however it also provides a number of fallbacks for browsers that do not support postMessage, giving us a broad base of browser support. It even works with the dreaded IE6.

EasyXDM exposes its transport stack via two object types:

  • Socket: Simple, bi-directional string-based messages.
  • RPC: Create a proxy object to make remote method calls.

The library also includes its own cors interface for making AJAX calls:

request(object config, function successFn, function errorFn)

For a full rundown see the easyXDM README on GitHub.

Security

The cors interface enforces access control so you can limit the access of remote resources to trusted servers. Trusted origins are configured with an array of strings or regular expressions:

var alwaysTrustedOrigins = [(/localhost/), (/mytrustedhost/)];

Setup

Host Site

The following files are used on the host site, though they can be hosted on a shared domain or CDN:

easyXDM.min.js The production version of easyXDM. For testing and debugging easyXDM.debug.js is available.
easyxdm.swf Facilitates the Flash transport fallback for IE 6 and 7.

Add the following on the host site to enable an additional IE 6/7 fallback:

name.html The NameTransport fallback (IE 6 and 7 without Flash).

Remote Site

On the remote resource site, the following two files are added. For this demo I uploaded them to a folder called “easyXDM” in the Azure storage container.

cors/index.html The easyXDM CORS interface.
name.html The NameTransport fallback (IE 6 and 7 without Flash).

The easyXDM library has no other dependencies or setup requirements.

Demo

Based on the xhr example in the easyXDM project, I created a simple demo that loads text-based resources using the Azure Blob Service REST API.  You can play with it in this jsFiddle:

Azure Storage easyXDM Demo

The demo page has two buttons that initiate AJAX calls.  The first loads an HTML fragment from a text resource.  The second loads JSON objects that contain a caption and an image thumbnail stored as Base64 encoded text.  I also included debug trace windows for both origins if you’re an “under the hood” type.

And of course, we’re not just limited to content served from Azure – see the Amazon S3 version of the demo as well.

Conclusion

The easyXDM library allows us to make cross-origin AJAX requests for text-based resources in Windows Azure Blob Storage.  With a lightweight deployment, wide browser support and the ability to limit access to trusted domains, we have opened up a new realm of possibilities for leveraging Azure Blob Storage.

More than that, easyXDM can come in handy any time you need to pull content via Ajax from one domain to another.  Unlike JSONP, it is not limited to JSON content.  As library author Øyvind Sean Kinsey notes in this excellent analysis, it can also be used for client-side messaging.  It really is a “Swiss army knife” for cross-domain/protocol/port messaging.