views:

359

answers:

2

I use simple PHP code (zend framework) to resize jpg images on the fly.

Problem is I always end up with HTTP 200 status, instead having 304 and allow browsers to cache images.

I cant get apache headers, function_exists('apache_request_headers') is false, and in server variable I have only

 'HTTP_ACCEPT' => 'image/png,image/*;q=0.8,*/*;q=0.5',
  'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
  'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
  'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
  'HTTP_CACHE_CONTROL' => 'max-age=0',
  'HTTP_CONNECTION' => 'keep-alive',
  'HTTP_COOKIE' => '***',
  'HTTP_HOST' => 'automobi.li',
  'HTTP_KEEP_ALIVE' => '300',
  'HTTP_REFERER' => 'http://automobi.li/oglas/Opel+Astra/2',
  'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 FirePHP/0.4',

I'm sending

    $lastModified = filemtime($path);
  $etag = md5_file($path);

  $this->getResponse()->setHeader('Content-type', 'image/jpeg');
  $this->getResponse()->setHeader('Cache-Control', 'public');
  $this->getResponse()->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
  $this->getResponse()->setHeader('Cache-Control', 'max-age=86400, must-revalidate');
  $this->getResponse()->setHeader('Expires', gmdate('D, d M Y H:i:s', time() + 86400 ) . ' GMT');
  $this->getResponse()->setHeader('ETag', $etag);

and I expected HTTP_IF_MODIFIED_SINCE or sth similar in server variable so I can do

  if ($this->getRequest()->getHeader('IF_MODIFIED_SINCE') == $lastModified) {
$this->getResponse()->setHttpResponseCode(304);

  } else {
   $w = (int) $this->_getParam('w');
   $h = (int) $this->_getParam('h');
   $image->resize($path, $w, $h);   
  }

Any idea?

A: 

The Last-Modified and If-Modified-Since values are not to be compared for equality. They both represent times. And if the Last-Modified time is greater than the If-Modified-Since time (so last modification took time after If-Modified-Since), the condition is fulfilled and 304 should be sent.

So you need to parse the If-Modified-Since value (try strtotime) and compare the values if the Last-Modified time is greater than the If-Modified-Since time:

if ($lastModified > strtotime($this->getRequest()->getHeader('IF_MODIFIED_SINCE'))) {
    $this->getResponse()->setHttpResponseCode(304);
}
Gumbo
Thanks, I know that, I just wrote it fast and didn't bother about detaiils. If you look at $_SERVER variable, you'll see that IF_MODIFIED_SINCE is not set, and as I already wrote, apache_request_headers is not defined function, and that is the main problem, I don't have this data! So I'm looking for a solution, how to determine it.
auto
If `$_SERVER['IF_MODIFIED_SINCE']` is not set, then the client didn’t sent the *If-Modified-Since* header field and you cannot use it to determine if the client’s representation is still fresh.
Gumbo
OK, but what to use instead? There must be some way to determine client cache.
auto
@auto: You just cannot do it. There can be multiple reasons for why that information is missing. For example because that’s the first request of that resource or client does not support caching.
Gumbo
@Gumbo I don't agree.1. It happens even if that is not the first request.2. Caching is supported by client, because it caches static resources (other images, js and css).
auto
@auto: The two reasons I mentioned are just examples. HTTP Caching is a complex topic.
Gumbo
Well, thanks, but I'm sure there must be the way :) If anybody can help, I would be thankful.
auto
@auto: There must be a way for what case? That there is no *If-Modified-Since* header? Then you maybe didn’t understand the purpose of *If-Modified-Since*.
Gumbo
A: 

Fixed with

$this->getResponse()->setHeader('Content-type', 'image/jpeg');
    $this->getResponse()->setHeader('Expires', '', true);
    $this->getResponse()->setHeader('Cache-Control', 'public', true);
    $this->getResponse()->setHeader('Cache-Control', 'max-age=3800');
    $this->getResponse()->setHeader('Pragma', '', true);
    $this->getResponse()->setHeader('ETag', $etag);

    if ($etag == $this->getRequest()->getHeader('If-None-Match')) {
        $this->getResponse()->setHttpResponseCode(304);
    } else {
        $w = (int) $this->_getParam('w');
        $h = (int) $this->_getParam('h');
        $image->resize($path, $w, $h);
    }

thanks to http://dustint.com/archives/25

When I added

$this->getResponse()->setHeader('Expires', '', true);
    $this->getResponse()->setHeader('Cache-Control', 'public', true);
    $this->getResponse()->setHeader('Cache-Control', 'max-age=3800');
    $this->getResponse()->setHeader('Pragma', '', true);

If-None-Match header in the request appeared, which helped me to match it against etag.

@Gumbo Oh, I understand it well :)

Thanks everyone who tried to help.

auto