Test suite for illegal request aborts in browser implementations

home info

Some browsers (firefox, safari) abort pending requests (ajax, images, websockets...) as soon as a new location is assigned to document.location.href (link is clicked, form is submitted, javascript assigns document.location.href).

The majority of browsers (chrome, internet explorer) do not abort any requests in this situation.
This site provides a test suite that detects whether a browser does abort requests when a new location is assigned.

If you have any questions regarding this site, please contact mirko.tschaeni [at] unblu.com

What is going wrong?

In short browsing context navigation consists of the following phases:

  1. Navigation is initiated (i.e. link is clicked, form is submitted, document.location.href is assigned)
  2. Various preparation steps (i.e. exit the navigation algorithm if a download link is clicked, handle fragment identifiers...)
  3. A fetch algorithm starts in in the background
  4. The fetch algorithm delivers a server response
  5. Perform various checks based on the response (i.e. hand over to external application (and cancel navigation), if the content-type cannot be rendered in the browser, show download dialog if content-disposition is attachement...)
  6. Unload the current document (fire unload event, cancel all pending fetch algorithms, close websockets, destroy javascript context...)
  7. Start parsing and rendering the new document

Browsers that are are affected will cancel all pending fetch algorithms in phase 2. To the web application this looks like a random error in the middle of document live cycle and there is no way to detect why these fetch algorithms (ajax request, images...) suddenly stopped loading.
For requests that are created after the location assignment (step 1), there are two different behaviors: In some browsers (firefox, chrome, internet explorer), they work normally, in other browsers (safari), they do not work at all (no fetching takes place, no events are fired).

If the navigation results in a hand over to an external application or in a download, the browser context will not navigate and will not unload, thus the document continues to live but might be corrupted due to aborted fetches (images, css, ajax, websockets...).

Which browsers are affected?

Within the tested browsers (Chrome, Firefox, Internet Explorer, Safari)...

...the following ARE affected:

Firefox (aborts requests on location assignment), see Issue 1084399, bugzilla.mozilla.org
Safari (aborts requests on location assignment, does not allow new requests until after location assignment, does NOT abort websockets), see Issue 137817, bugs.webkit.org and Issue 23933, bugs.webkit.org

...and the following ARE NOT affected:

Internet Explorer
Chrome (used to be affected until version 36)

Why is aborting requests on location assignment problematic?

At the time a new location is assigned (click on link, form submit, document.location.href assignment), it is impossible to tell whether the started navigation will result in a new document being loaded in the current browser context or not. Only when the response has arrived, it is possible to know whether the content can be rendered in the browser. Aborting requests early (at the time of the location assignment) is premature and can cause various problems. ...especially if a web application consists of components from different vendors that do not have full control over the whole application.

  1. Components that rely on client/server communication must be able to deals with random request aborts
  2. Documents might not fully render because image or css fetches are stopped
  3. Documents might be corrupted because some resource loads were aborted
  4. It is not possible to tell resource aborts caused by location assignment from other aborts (the situation cannot be detected)
  5. File upload monitoring after a form submit is impossible

Especially if the started navigation ends in something that is not rendered in the browser, this can leave the current document in a currupted state even if the page remains displayed as if the navigation had never started.

What does the spec say?

The spec (https://html.spec.whatwg.org/multipage/browsers.html) describes navigation here: https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents, in step 12 it references https://html.spec.whatwg.org/multipage/browsers.html#abort-a-document which basically says that the document load should be aborted when a location is assigned.

I think the spec is wrong (or not precise enough) here:

https://html.spec.whatwg.org/multipage/browsers.html#abort-a-document titles "Aborting a document load" which indicates that this algorithm must only be applied to documents that are not fully loaded.
In addition to this ambiguity i think that
https://html.spec.whatwg.org/multipage/browsers.html#abort-a-document should be overthought.
https://html.spec.whatwg.org/multipage/browsers.html#abort-a-document is invoked when the user presses the stop button, which i think is ok. However the stop button might make the user think that the page will be stopped completely. However this is not the case: javascript execution is not stopped, in most browsers javascript can spawn new requests (ajax, images, websockets). I think that the stop button should stop everything (parsing, script execution, requests, websockets, workers...).

I also think that https://html.spec.whatwg.org/multipage/browsers.html#navigating-across-documents should not invoke https://html.spec.whatwg.org/multipage/browsers.html#abort-a-document because at this time it is impossible to tell whether the started navigation is going to affect the current browsing context at all or not.

What is tested?

The tests on this site test whether fetch algorithms are aborted by location assignments before the response has reached the browser.
First a request is created to a resource that only responds after a given amount of time. Within this amount of time, document.location.href is assigned to see whether the pending request gets aborted. In order to have enough time for analysing whether requests are aborted, the url of the location assignment also responds slowly. The tests can be run in a different configurations, testing different scenarios:

Type of request

The type of the request that is tested can be one of: ajax, image or websocket

For ajax a simple async ajax request is created.

For image a javascript Image object is created and the src property is assigned.

For websocket a WebSocket is opened and tested using a simple echo service.

For most browsers the type does not matter (all requests are aborted). Exception: safari does not abort(close) websockets.

Document life cycle phase

The test can be run in different phases of document life cycle. Loading: before the load event has fired on window

Loaded: after the load event has fired on window

Navigating: after a location assignment has taken place (this is in order to test how new requests after the assignment are treated)

All tests are guaranteed to run BEFORE the unload event.

Origin of the resource

The test can be run against resources that are same origin or from a third party origin (xorigin). same: the resource is loaded from the same origin as the current document

xorigin: the resource is loaded from a origin that is different form the origin of the current document

Whether a resource is fetched from same origin or not does not seam to influence the outcome of the test.