Handling If-modified-since header in a PHP-script
if-modified-since, php
Solution
This is definitely possible in PHP!
When the browser checks if there were modifications, it sends an `If-Modified-Since` header; in PHP this value would be set inside `$_SERVER['HTTP_IF_MODIFIED_SINCE']`.
To decode the date/time value (encoded using rfc822 I believe), you can just use `strtotime()`, so:
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) &&
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($localFileName))
{
header('HTTP/1.0 304 Not Modified');
exit;
}
Explanation: if the `If-Modified-Since` header is sent by the browser AND the date/time is at least the modified date of the file you're serving, you write the "304 Not Modified" header and stop.
Otherwise, the script continues as per normal.
Problem
I have a PHP script which is called with an ?img= parameter. The value for that parameter is an (urlencoded) URL of an image. My script checks, if that image is already stored at my server. If not - it downloads it. After that it optionally resizes the image and sends it to STDOUT, i.e. back to the requesting browser, prepended with Content-Type and Last-modified headers: ``` Connection:close Content-Type:image/jpeg Date:Fri, 01 Jun 2012 08:28:30 GMT Last-Modified:Fri, 01 Jun 2012 08:02:44 GMT Server:Apache/2.2.15 (CentOS) Transfer-Encoding:chunked X-Powered-By:PHP/5.3.3 ``` This is needed to workaround some crossdomain issues and works well for me since over a year: However I'd like to add functionality to handle the incoming If-Modified-since header - to send a Not Modified 304 response. My questions are: 1) Is that even possible in PHP, when run in Apache? 2) How to handle (i.e. parse and produce) the dates best in PHP here? Bonus question) How to add a Content-Length header for the resized images? My code is below (I've omitted the CURL-downloading part): ``` <?php define('CACHE_DIR', '/var/www/cached_avatars/'); $img = urldecode($_GET['img']); $cached = CACHE_DIR . md5($img); # omitted downloading part for brevity $readfh = fopen($cached, 'rb'); if ($readfh) { flock($readfh, LOCK_SH); $size = getimagesize($cached); $w = $size[0]; $h = $size[1]; $type = $size[2]; $mime = $size['mime']; # find the downscale factor to fit image into $maxw x $maxh $scale = max($w / $maxw, $h / $maxh); header('Content-Type: ' . $size['mime']); header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($cached))); $length = filesize($cached); $buf = fread($readfh, $length); fclose($readfh); # the image is smaller than $maxw x $maxh, do not scale up if ($scale <= 1) { header('Content-Length: ' . $length); print($buf); return; } $tw = $w / $scale; $th = $h / $scale; $image = imagecreatefromstring($buf); $thumb = imagecreatetruecolor($tw, $th); imagecopyresampled($thumb, $image, 0, 0, 0, 0, $tw, $th, $w, $h); imagedestroy($image); # How to add Content-Length here, after image resizing? if (IMAGETYPE_JPEG == $type) imagejpeg($thumb, null, 75); else if (IMAGETYPE_PNG == $type) imagepng($thumb, null, 9); else if (IMAGETYPE_GIF == $type) imagegif($thumb, null); imagedestroy($thumb); } ?> ```