Cross-origin data access from JavaScript

WattDepot features a RESTful API that emits XML, and supports the Google Visualization API using the Google-provided Java library. There is a Java client library that makes it easy to write WattDepot clients in Java, and Google provides a library for JavaScript clients using the Google Visualization API. A several Java clients have been written and several JavaScript clients have been written.

Yichi Xu is working on a GeoMap visualization for WattDepot, and it needs to use the REST API rather than the Visualization API. This means he had to query the REST API directly, and parse the resulting XML. He quickly ran into the same-origin policy in JavaScript. In short, scripts running from a particular domain can generally only access resources from that same domain. This makes sense, because you don’t want any random web page you browse to have access to all your email just because you have a Gmail window up. However, from a developer’s perspective, this is a big when you want to use an HTTP API. Yichi’s gadget is loaded either locally or from Google’s servers, so when it tries to perform an HTTP GET to the WattDepot servers, it fails due to the same-origin policy.

There are a few workarounds for this problem, and Nelson Minar provides a good introduction. You can use proxies, but that’s gross. The most common solution makes use of a loophole in the same-origin policy: you can load JavaScript code from anywhere (just not data). So if you wrap your data so that it looks like code, then you can violate the same-origin policy. If you are providing the data in the JSON format, once wrapped it becomes JSONP.

Right now, WattDepot doesn’t support JSON representations (though it may in the future), so the JSONP trick is not available to us. Luckily, Yichi came across this draft from W3C on Cross-Origin Resource Sharing. CORS allows servers to emit HTTP headers that indicate how browsers should restrict access to the resource. The header can open things up so anyone can use the resource, or only certain other domains. However, this requires browsers to act on the header, luckily Firefox 3.5 and the latest Safari both implement this (the Firefox page has an excellent discussion of CORS). For now, supporting Firefox 3.5 and Safari is acceptable, so WattDepot just emits “Access-Control-Allow-Origin: *” for all requests. In the future this will be cleaned up to only emit this for public sources, and also provide JSON and JSONP representations for easier use in JavaScript.