Max-age=0 sent by browsers despite headers modified everywhere

apache-2.2cachechromefirefoxhttp-headers

I have a headers/cache issue in my lamp [centos] website.

Config:

[root@localhost httpd]# httpd -v
Server version: Apache/2.2.23 (Unix)
Server built:   Nov 25 2012 15:03:00

[root@localhost httpd]# php -v
PHP 5.5.22 (cli) (built: Feb 20 2015 04:04:46)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2015, by Zend Technologies

php.ini:

session.cache_limiter = public
session.cache_expire = 535680

httpd.conf:

<IfModule mod_expires.c>
    # enable expirations
    ExpiresActive On
         <FilesMatch "\.(php)$">
                ExpiresDefault "access plus 1 month"
                Header set Cache-Control "max-age=32140800, public"
                Header unset ETag
                Header unset Last-Modified
                FileETag None
         </FilesMatch>
</IfModule>

Meta tags:

<meta HTTP-EQUIV="cache-control" CONTENT="public, max-age=32140800">

The Issue:

  1. Load the page for the first time (named si.php here)
  2. Clean access_log:

    [root@localhost httpd]# > access_log
    
  3. Press F5 in firefox/chrome:

    [root@localhost httpd]# cat access_log
    192.168.0.16 - user [25/Jun/2015:04:16:19 +0100] "GET /path/si.php HTTP/1.1" 200 642 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.130 Safari/537.36"
    
  4. Observe Http headers with live http headers firefox extension:

    http://192.168.0.249/path/si.php
    
    GET /path/si.php HTTP/1.1
    Host: 192.168.0.249
    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    DNT: 1
    Cookie: __utma=254085576.10126650.1407082841.1422764987.1429480306.10; __utmz=254085576.1407082841.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); PHPSESSID=1cuf6d8764vu2i2u1hin4pg665
    Authorization: Basic cmVjZqR0ZTq1c2VyMQ==
    Connection: keep-alive
    Cache-Control: max-age=0
    
    HTTP/1.1 200 OK
    Date: Thu, 25 Jun 2015 03:18:04 GMT
    Server: Apache
    X-Powered-By: PHP/5.5.22
    Expires: Fri, 01 Jul 2016 03:18:04 GMT
    Cache-Control: max-age=32140800, public
    Vary: Accept-Encoding,User-Agent
    Content-Encoding: gzip
    Content-Length: 643
    Keep-Alive: timeout=15, max=13
    Connection: Keep-Alive
    Content-Type: text/html; charset=utf-8
    

Why on earth is the max-age=0 header sent? Firefox and Chrome display both the same behavior. This is an extra 170ms I currently cannot afford.

What is even weirder is the 200 http response code. I don't modify the page at all, it should at the very least return a 304…


Edit:

Ok, as accepted answer proposes, solution is to:

  1. not open a fresh browser (might not retrieve from cache)
  2. not pressing f5
  3. not just pressing enter in address bar

After the page has been visited a first time in this browser instance, any subsequent normal visit will be from cache:

enter image description here

Best Answer

When you hit F5 in a browser, you are instructing the browser to ask the sever and any proxies in the path for new content. That Cache-Control request header does just that. It does not get added during normal navigation.

Also, PHP has no way of knowing that your content didn't change, especially if it is making a database call. It will never return a 304 for a request unless you add code that makes it do so under whatever conditions. The reason you set a cache-control response header is so the browser won't even make a request at all if the resource is in cache.

Stop hitting F5, browse normally, and watch the traffic with Fiddler or similar tool. You'll find that when you visit your PHP page, then go somewhere else, then come back without hitting F5 that your browser shows your PHP page without even requesting it from the server at all. You're changing that normal caching behavior by hitting F5!