PHP/Ajax "Vary: X-Requested-With" does not work for me!

1.8k Views Asked by At

i am trying to serve cacheable Content depending on whether it is an ajax request or not.

Scenario:

A little PHP-script "/test.php" serves some HTML-Output and sets the following Headers:

Expires         Wed, 23 Feb 2011 13:30:06 GMT
Cache-Control   public, max-age=60
Vary            X-Requested-With,Accept-Encoding

The Output depends on the $_SERVER['HTTP_X_REQUESTED_WITH'] state.

When my Firefox points to the Url i get the output, and for the next Minute i get the same result from the Browser-Cache, not hitting the server. OK, so far.

When I request the same resource via a XMLHttpRequest (with X-Requested-With: XMLHttpRequest Header), my Firefox does NOT request the Server, but serves the (wrong) response from Cache!

For the other way round, its the same. An Ajax-Call on the resource fills the cache, and a subsequent Browser-Request serves the (wrong) response from Cache.

Does anyone have experience with this topic? I think this should be a common enough issue - serving content depending on whether its ajax or not (on the same URL).

greetings, Ilja

1

There are 1 best solutions below

2
On

I can reproduce this, but only if I don't include the X-Requested-With header in the ajax response. If I set the header for the ajax call, it works mostly as expected, although the ajax call clears the cache for the regular request and vice-versa - content does not get cached, but you never get the wrong content.

My PHP doc looks like this:

<?
    putenv('TZ=PST8PDT');
    date_default_timezone_set('America/Los_Angeles');

    header('Expires: '.gmdate("D, d M Y H:i:s").' GMT');
    header('Cache-Control: public, max-age=60');
    header('Vary: X-Requested-With,Accept-Encoding');

    echo 'it is now '.date('Y-m-d H:i:s');
?>

And my test page like this:

<a href="resource.php" target="ifr">load into frame</a><br />
<iframe name="ifr" width="400" height="100"></iframe>

<hr />

<a href="#" onclick="return load();">load into div via ajax</a><br />
<div id="di" style="border: 1px solid black; width: 400px; height: 100px;"></div>

<script>

function load(){

    var req = new XMLHttpRequest();
    req.onreadystatechange = function(){

        if (req.readyState == 4){
            document.getElementById('di').textContent = req.responseText;
        }
    }

    req.open('GET', 'resource.php', 1);
    req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    req.send(null);

    return false;
}

</script>

When I hit the first link, it requests from the server. When I hit it again, it comes from cache. Every subsequent click comes from cache, up to 60 seconds.

When I hit the second link, the request goes to the server. When I hit it again, it comes from cache. Every subsequent click comes from cache, up to 60 seconds.

If I hit link 1, then link 2, they both go to the server. If I then hit link 1 again, it goes to the server again (which is wrong). Demo sequence (assuming all within 60s):

Reg  : server
Reg  : cache
Reg  : cache
Reg  : cache
Ajax : server
Ajax : cache
Reg  : server
Ajax : server

The upshot is, if you want to reliably cache things differently when served via ajax, use a different URL when making the ajax request (?ajax=1 would work fine).

I'm testing on FF 4.0 latest