This page tests how XHR requests are cached.
This issue was initially discussed in a HttpWatch blog post.
In that post, it was mentioned that:
...any Ajax derived content in IE is never updated before its expiration date - even if you use a forced refresh (Ctrl+F5).
The only way to ensure you get an update is to manually remove the content from the cache.
This is surprisingly true.
This test page explores this a bit more.
This page contains an image, an external script, and an XMLHttpRequest.
The expiration time varies depending on which link you select above.
- Expires in the Past adds an Expires response header with a date 30 days in the past, and a Cache-Control header with a max-age value of 0.
- no Expires does not return any Expires nor Cache-Control headers.
- Expires in the Future adds an Expires response header with a date 30 days in the future, and a Cache-Control header with a max-age value of 2592000 seconds.
| Table 1. When XHR is cached, what happens when you hit F5? |
| | Past Expires | No Expires | Future Expires |
| Chrome 2 | 304 | 304 | 304 |
| Firefox 3.5 | 304 | 304 | 304 |
| IE 7 | 304 | cache | cache |
| IE 8 | 304 | cache | cache |
| Opera 10 | 304 | cache | 304 |
| Safari 4 | 200 | 200 | 200 |
Table 1 shows the results of testing this page on major browsers.
The test was to click on a link (e.g., Expires in the Past) and then hit F5.
The result recorded in the table is whether the XHR was re-requested or read from cache, and if it was re-requested what was the HTTP status code.
Here's what happens when F5 is hit:
- All browsers re-request the image and external script. (This makes sense.)
- All browsers re-request the XHR if the expiration date is in the past. (This makes sense - the browser knows the cached XHR is expired.)
- The only variant behavior has to do with the XHR when there is no Expires or a future Expires.
IE 7&8 do not re-request the XHR when there is no Expires or a future Expires, even if control-F5 is hit.
Opera 10 does not re-request the XHR when there is no Expires. (I couldn't find an equivalent for control-F5 in Opera.)
- Both Opera 10 and Safari 4 re-request the favicon.ico in all situations. (This seems wasteful.)
- Safari 4 does not send an If-Modified-Since request header in all situations. As a result, the response is a 200 status code and includes the entire contents of the original response.
This is true for the XHR as well as the image and external script.
(This seems wasteful and deviates from the other browsers.)
Takeaways
- Developers should either set a past or future expiration date on their XHRs, and avoid the ambiguity and variant behavior when no expiration is specified.
- If XHR responses should not be cached, developers should assign them an expiration date in the past.
- If XHR responses should be cached, developers should assign them an expiration date in the future. When testing in IE 7&8, developers have to remember to clear their cache when testing the behavior of Reload (F5).
- Opera and Safari should stop re-requesting favicon.ico when F5 is hit.
- Safari should send If-Modified-Since when F5 is hit.