Meteor

An HTTP server for the 2.0 web

Welcome to Meteor - you're a star! (Learn more)
Because Meteor and your normal web server have to live side by side, we had to find ways of loading information from Meteor in pages served by Apache, after the page has finished loading. This page examines all the ways this can be done and documents which ones work for which browsers.

There are three main mechanisms that can be used to load data asyncronously once a page is loaded:

All of these work well enough when retrieving data from the same server that served the page (at least in all the browsers under test below), but the problems arise when you want to retireve data from a different host or port, because you run into security restrictions implemented in the browser.

Some other comet implementations include a proxy engine that allows the comet server to handle all the requests directly, and pass non-comet requests through to a hidden web server, but Meteor does not support that style of behaviour, and there are some very good reasons to avoid doing it in this way.

The behaviours

All these results come from observations using these tests.

T'portConfigurationIE 6/7FF 2Op 9Saf 2Saf 3iPhone
XHR one-part, same-origin Yes Yes Yes Yes Yes Yes
one-part, same host, different port Yes No No No No No
one-part, parent host, same port No No Yes2 No No No
one-part, parent host, different port No No No No No No
incremental, same-origin No8 Yes No9 No3 No3 Yes
incremental, same-origin, 1K prepended 'noise' No8 Yes No9 Yes Yes Yes
incremental, same host, different port No8 No No9 No No No
incremental, same host, different port, 1K prepended 'noise' No8 No No9 No No No
incremental, parent host, same port No No No9 No No No
incremental, parent host, same port, 1K prepended 'noise' No No No9 No No No
incremental, parent host, different port No No No No No No
incremental, parent host, different port, 1K prepended 'noise' No No No No No No
T'portConfigurationIE 6/7FF 2Op 9Saf 2Saf 3iPhone
IFRAME one-part, same-origin Yes1 Yes1 Yes1 Yes1 Yes Yes
one-part, same host, different port Yes1 Yes1 No No Yes1 No
one-part, parent host, same port Yes1 Yes1 Yes1 Yes1 Yes1 Yes1
one-part, parent host, different port Yes1 Yes1 No No Yes1 No
incremental, same-origin No3 Yes1 Yes1 No3 No3 Yes
incremental, same-origin, 1K prepended 'noise' Yes1 Yes1 Yes1 Yes Yes Yes
incremental, same host, different port No3 Yes1 No No No3 No
incremental, same host, different port, 1K prepended 'noise' Yes1 Yes1 No No Yes1 No
incremental, parent host, same port No3 Yes1 Yes1 No3 No3 Yes
incremental, parent host, same port, 1K prepended 'noise' Yes1 Yes1 Yes1 Yes1 Yes1 Yes
incremental, parent host, different port No3 Yes1 No No No3 No
incremental, parent host, different port, 1K prepended 'noise' Yes1 Yes1 No No Yes1 No
T'portConfigurationIE 6/7FF 2Op 9Saf 2Saf 3iPhone
SCRIPT one-part, same-origin Yes Yes Yes Yes Yes Yes
one-part, same host, different port Yes Yes Yes No Yes No
one-part, parent host, same port Yes Yes Yes Yes Yes Yes
one-part, parent host, different port Yes Yes Yes No Yes No
any incremental-loading configuration No No No No No No
Shorten document.domain Yes Yes Yes Yes Yes Yes
Lengthen document.domain to original length once shortened Yes No No No7 No7 No7
T'portConfigurationIE 6/7FF 2Op 9Saf 2Saf 3iPhone

Table notes

  1. IFRAME can only be accessed if its document.domain matches the parent frame's document.domain
  2. XHR can only be made if document.domain is a match for or a parent of the target host. This will always be the case for XHRs to the originating host, but document.domain must be shortened to allow XHR to the parent domain.
  3. Safari and IE have a buffer which must fill up before any response is parsed. Data received before the buffer is full will not be rendered or interpreted and will not fire the Interactive state of an XHR until the buffer is full or the connection is closed. The obvious solution to this is to send a blob of 'noise' at the start of any response that needs to be parsed incrementally. The size of the buffer that needs to be filled is 512 bytes in Internet Explorer, and between 256 bytes and 1K in Safari depending on the Content-type of the response (a non-standard content-type equals a 256b buffer, while a text/html content type may be as much as 1K)
  4. SCRIPT loading is a blocking action in Opera, non-blocking in other browsers.
  5. In Safari, HTTP URLs that do not explicitly define a port number (and therefore default to port 80 in all browsers) are considered to have a different port to those URLs that do explicity define port 80, even though both URLs actually use the same port. The test suite therefore defines 'same port' as 'no port specified', rather than explicitly setting :80.
  6. Despite setting cache-busting headers, you must give every script you load using the SCRIPT transport a unique URL, else the browser may simply pull the existing script out of memory and run it again.
  7. Fails silently, does not throw an error
  8. In Internet Explorer, the first incremental response to XHRs does fire a readyState 3 'interactive' event, but neither the body nor the headers of the response are available until the response is complete, making these events essentially useless. So for the purposes of incrementally downloading data into the browser, the incremental XHR is considered non-functional in IE.
  9. Although the responseText property of the XHR is available while the response is still being received, Opera only fires the readyState 3 'interactive' event once, so subsequent packets received will not be processed.

The tests

If you want to see the results for a different browser that's not listed above, go run the tests yourself and contribute the results, we'll add them to the table above.

Conclusions

The way Meteor is designed to work is compatible with all of these browsers, in that a subdomain frame can talk to a parent domain frame, and all actual server conenctions can be made to same-origin from the subdomain frame. Separating the comet server from the web server using ports won't work in Safari 2 or Opera.