The Problem:

Accessing properties or executing methods on that is retrieved from a different origin is not permitted because of the “same origin policy” browser security concept. This includes accessing scripts and RESTful from one page to a separate resource on a different protocols, hosts or ports.

 

The General Solution:

The best approach is to host JavaScript and JSON resources on the same domain. The future approach, or current approach if you are only supporting modern browsers, is to use the  Cross-Origin Resource Sharing approach. However, there are workarounds and hacks to work around the same origin policy for legacy browsers.

 

The Workarounds:

Cross-Origin Resource Sharing (Recommended)

Cross-Origin Resource Sharing (CORS) is a web browser technology specification, which defines ways for a web server to allow its resources be accessed by a web page from a different domain. Such access would otherwise be forbidden by the same origin policy. This is available on the latest browsers including Firefox 3.5+, WebKit based browsers including Safari 4+, Chrome 3+, and IE8+ (using a special IE only XDomainRequest object). The CORS request requires the use of an origin header and the server must supply a special access-control-allow-origin header confirming that the communication is allowed. Dojo supports the basic AJAX support for this natively, but it appears that special handling will need to be written to support IE’s XDomainRequest Object.

JSONP

The JSON with Padding (JSONP) pattern uses a Script tag workaround to make GET requests that pull back a JavaScript file containing a callback function with JSON as the argument. This would execute the local function which could set the JSON argument to an accessible variable. The limitation with this method is that it breaks the RESTful model as it only supports GET.

Cross-document messaging (web messaging)

CDM is an API introduced in the WHATWG draft specification, allowing documents to communicate with one another across different origins, or source domains. It uses ’s postMessage method to allow plain text messages to be sent from one domain to another. This option is only available for the latest browsers. It isn’t very RESTful and although it is perfect to send simple string messages, it is not viable as a means to transport large chunks of structured data.

document.domain

One solution allows the document.domain property to be mutually set to a common top-level domain value. This will allow access to the JavaScript DOM despite failing the “same host” check. For example, if http://www.example.com and http://api.example.com both set document.domain to “example.com”, they would be from that point on considered same-origin for the purpose of DOM manipulation. If resources exist on another domain, this method could be used by created a CNAME on the same domain that points to the foreign domain. Not a bad solution, but could break RESTful principals and JSON responses.

Server-side Proxy

This method uses a server-side proxy for the JavaScript resources on the same domain. Could be a useful solution in some scenarios.

 

Old School Workarounds:

Script tag GET

The HTML script tag performs an HTTP GET operation that is not subject to the origin policy and retrieved JavaScript can be executed and parsed normally. Only supports GET and won’t support RESTFul principles.

Form POSTs

HTML forms do not adhere to the same origin policy and can perform HTTP POSTs of information to other domains. Sounds like a lot of work to manage and could easily become a mess.

iFrame Communication

A loophole that uses nested iframes to communicate using DOM access. This was the preferred workaround for a long time until CORS. The models for this make my head hurt. This method is not clean and would be difficult to manage.

window.name Transport

This method sets the window name of a child window to a JSON string that can be retrieved and parsed. The frame can be POSTed to for communication and return responses via the window name. This feels really messy.

Flash Method

Using flash as a cross-domain proxy is an available option. I think the problems here are obvious as it is in the title.

Fallback libraries

There are libraries available to us that will use CORS for modern browser and fall back to the hack work arounds in order to provide a full array of cross-browser support. These might be a great option if you need an option to support legacy browsers.