PHP setting Etag reliably

Peter John picture Peter John · Aug 12, 2010 · Viewed 10.6k times · Source

im having trouble setting the Etag on a user's browser reliably. When a user clicks on one of my external links, i would like to set the article id into their Etag (i use cookies too, but id like to experiment with Etag specifically to test its reliability).

When the same user returns to my site a few hours/days later, i would like to be able to read the Etag value and use it for stuff.

I can set an Etag on the initial click, but when the user returns the Etag value is gone. I assume its expired or something. Here is the code i have been trying:

<?

$time = 1280951171;
$lastmod = gmdate('D, d M Y H:i:s \G\M\T', $time);
$etag = '123';


$ifmod = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $lastmod : null; 
$iftag = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? $_SERVER['HTTP_IF_NONE_MATCH'] == $etag : null; 

if (($ifmod || $iftag) && ($ifmod !== false && $iftag !== false)) { 
    header('HTTP/1.0 304 Not Modified'); 
} else {
    header("Last-Modified: $lastmod"); 
    header("ETag: $etag");
}

print_r($_SERVER);

?>

Answer

Alan Pearce picture Alan Pearce · Aug 12, 2010

You should be wrapping your etag in double quotes (as the link Codler mentioned shows):

'"' . $etag . '"'

I don't think it's likely to solve your problem, but you probably want

header('Not Modified',true,304);

instead of

header('HTTP/1.0 304 Not Modified');

As of PHP 5.4 there's a better way to do this with http_response_code:

http_response_code(304);

Also, have you checked for the usual suspects stopping headers? Unicode Byte-Order Markers are very annoying with this. (Disregard if you can see other headers you're setting yourself)