Visit Mozilla.org

Cross-Site XMLHttpRequest

From MDC

Firefox 3 note

This feature is available in Firefox 3, but only to extensions and other privileged code; it is not currently available for web content.

Firefox 3 implements the W3C Access Control working draft, which gives you the ability to do XMLHttpRequests to other web sites.

Contents

[edit] Overview

The W3C Access Control structure gives client-side documents greater control over who can, and cannot, request them via a browser-based request (such as via an XMLHttpRequest).

Additionally, this access control scheme gives applications the ability to allow for cross-site requests. Thus one could, theoretically, request a document from google.com, via an XMLHttpRequest in a page on yoursite.com (once the access control points were put in place). This level of control gives content creators greater amounts of flexibility when it comes to allowing their users to build mashups and applications using their information.

[edit] Usage

There are two methods through which you can use the W3C Access Controls in Firefox 3. The first is through the addition of a new Access-Control header (which is usable for all resource types and when you have a greater of level control over your web server) and the access-control processing instruction (which is only useful for XML documents).

[edit] Access-Control Headers

This is the most flexible means of allowing cross-site XMLHttpRequests. Specifically, if you provide an additional Access-Control header in your request response, like the following, which will grant access to any web application on mozilla.org.

Access-Control: allow <mozilla.org>

The Access-Control header gives you the ability to grant or exclude access to a resource based upon its origin and method of request.

For example, all of the following are valid Access-Control headers:

// Anyone is allowed to access this resource - no restrictions
Access-Control: allow <*>

// Everyone is denied access to this resource - no exceptions
Access-Control: deny <*>

// Only sites that are hosted on 'mozilla.org' may access this resource
// (this includes sub-domains as well)
Access-Control: allow <mozilla.org>

// All sub-domains but developer.mozilla.org, of mozilla.org, can access this resource
Access-Control: allow <mozilla.org> exclude <developer.mozilla.org>

// Only this domain, on this port, with this request method can access the resource
Access-Control: allow <developer.mozilla.org:80> method GET, POST

Some more examples of sample patterns can be found in the W3C Access Control working draft.

[edit] Example

This simple example requests an HTML file from a separate web site. That particular HTML file is generated by a PHP script which outputs the extra Access-Control header. If you were to copy header.html to your own server you would see that the request would continue to work (since all sites are allowed to submit to it).

header.html

<html>
<head>
<script>
window.onload = function(){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "http://dev.jquery.com/~john/xdomain/test.php", true);
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 ) {
      if ( xhr.status == 200 ) {
        document.body.innerHTML = "My Name is: " + xhr.responseText;
      } else {
        document.body.innerHTML = "ERROR";
      }
    }
  };
  xhr.send(null);
};
</script>
</head>
<body>
Loading...
</body>
</html>

test.php

<!-- Change this to allow <yourdomain.com> to make it accessible to your site, or allow <*> for ANYONE to be able to access it. -->
<?php header('Access-Control: allow <ejohn.org>'); ?>
<b>John Resig</b>

[edit] XML Processing Instruction

XML includes the ability to include extra commands for the XML processor to handle specially. The Access Control draft specifies a way to provide an extra one of these commands such that any XML document can become remotely accessible, in a cross-site manner.

For example, including the following access-control processing instruction would give any site at mozilla.org the ability to access the XML document it was included in:

<?access-control allow="mozilla.org"?>

Here's some simple examples of using the access-control processing instruction to grant privileges for XML document access:

// Anyone is allowed to access this resource - no restrictions
<?access-control allow="*"?>

// Everyone is denied access to this resource - no exceptions
<?access-control deny="*"?>

// Only sites that are hosted on 'mozilla.org' may access this resource
// (this includes sub-domains as well)
<?access-control deny="mozilla.org"?>

// All sub-domains but developer.mozilla.org, of mozilla.org, can access this resource
<?access-control allow="mozilla.org" exclude="developer.mozilla.org"?>

// Only this domain, on this port, with this request method can access the resource
<?access-control allow="developer.mozilla.org" method="GET POST"?>

Some more examples of sample patterns can be found in the W3C Access Control working draft.

[edit] Example

This simple example requests an XML file from a separate web site. That particular XML file includes an access-control processing instruction which grants access to any web site requesting it. If you were to copy ac.html to your own server you would see that the request would continue to work (since all sites are allowed to submit to it).

ac.html

<html>
<head>
<script>
window.onload = function(){
  var xhr = new XMLHttpRequest();
  xhr.open("GET", "http://dev.jquery.com/~john/xdomain/test.xml", true);
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 ) {
      if ( xhr.status == 200 ) {
        document.body.innerHTML = "My Name is: " +
          xhr.responseXML.getElementsByTagName("name")[0].firstChild.nodeValue;
      } else {
        document.body.innerHTML = "ERROR";
      }
    }
  };
  xhr.send(null);
};
</script>
</head>
<body>
Loading...
</body>
</html>

test.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Change this to allow="yourdomain.com" to make it accessible to your site, or allow="*" for ANYONE to be able to access it. -->
<?access-control allow="ejohn.org"?>
<simple><name>John Resig</name></simple>

[edit] References

[edit] See also