This is about some code I inherited; the intent is clear, but (at least in Firefox and Chrome) it is not behaving as intended.
The idea is clearly to build a PNG based on client-side data and to cache it unless and until that data changes. The intent presumably is that the state of the PNG is preserved regardless of whether or not the client is using cookies, local storage, etc., but at the same time the server does not preserve data about this client.
Client-side JavaScript:
function read_or_write_png(name, value) {
// WRITE if value is defined, non-null, etc., get otherwise
if (value) {
// WRITE
// Use cookie to convey new data to server
document.cookie = 'bx_png=' + value + '; path=/';
// bx_png.php generates the image
// based off of the http cookie and returns it cached
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'bx_png.php?name=' + name; // the magic saying "load this".
// 'name' is not consulted server-side,
// it's here just to get uniqueness
// for what is cached.
} else {
// READ
// Kill cookie so server should send a 304 header
document.cookie = 'bx_png=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/';
// load the cached .png
var img = new Image();
img.style.visibility = 'hidden';
img.style.position = 'absolute';
img.src = 'bx_png.php?name=' + name;
}
}
Server-side PHP in bx_png.php:
if (!array_key_exists('bx_png', $_COOKIE) || !isset($_COOKIE['bx_png'])) {
// we don't have a cookie. Client side code does this on purpose. Force cache.
header("HTTP/1.1 304 Not Modified");
} else {
header('Content-Type: image/png');
header('Last-Modified: Wed, 30 Jun 2010 21:36:48 GMT');
header('Expires: Tue, 31 Dec 2030 23:30:45 GMT');
header('Cache-Control: private, max-age=630720000');
// followed by the content of the PNG
}
This works fine to write the PNG the first time and cache it, but clearly the intention is to be able to call this again, pass a different value for the same name, and have that cached. In practice, once the PNG has been cached, it would appear (via Fiddler) that the server is not called at all. That is, on an attempted read, rather than go to the server and get a 304 back, the browser just takes the content from the cache without ever talking to the server. In and of itself, that part is harmless, but of course what is harmful is that the same thing happens on an attempted write, and the server never has a chance to send back a distinct PNG based on the new value.
Does anyone have any idea how to tweak this to fulfill its apparent intention? Maybe something a bit different in the headers? Maybe some way of clearing the cache from client-side? Maybe something else entirely that I haven't thought of? I'm a very solid developer in terms of both server-side and client-side, but less experienced with trickiness like this around the HTTP protocol as such.