Search code examples
phpnginxhttp-headers

Why won't browsers cache files output by PHP readfile()?


I am currently outputting some image files via PHP's readfile() using the following code but, I notice via Firefox and Chrome's dev tools that none of these files get cached.

ob_start();
outputfile($fp);

function outputfile( $fp ) {

  header("Content-Type: $mime_type");
  header("Content-Length: " . filesize($fp));
  header("Cache-Control: public, max-age=3600");
  header("Etag: " . md5_file($fp));
  $date = gmdate("D, j M Y H:i:s", filemtime($fp))." GMT";
  header("Last-Modified: $date");

  readfile($fp);
  exit; // tried ob_end_flush() too before exiting

}

The code outputs the file with the following in the headers in the dev tools...

Cache-Control: public, max-age=2678400
Connection: keep-alive
Content-Length: 155576
Content-Type: image/jpeg
Date: Mon, 21 May 2018 22:31:02 GMT
Last-Modified: Sat, 03 Mar 2018 19:34:05 GMT
Etag: 507f2520385c009a7385a1165032bd61
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Server: nginx

If I return control to Nginx to serve the file instead, it outputs the following headers:

Accept-Ranges: bytes
Connection: keep-alive
Content-Length: 155576
Content-Type: image/jpeg
Date: Mon, 21 May 2018 22:31:02 GMT
ETag: "5a9af8ad-4a5b"
Last-Modified: Sat, 03 Mar 2018 19:34:05 GMT
Server: nginx

Am I missing something that causes the browsers to not cache the image files?

I've tried adding all the necessary Cache-Control headers such as eTag and max-age but, the browsers just refuses to cache the data. I even tried copying all the headers from the server's output and using "ob_start('ob_gzhandler');" in case it was because the raw file data wasn't gzipped.

The browsers just won't cache any file data sent through PHP.


Solution

  • I think I've found the problem...

    Was wondering if any cookie related code could affect readfile() and discovered that if I had session_start() before using the function, browsers will refuse to cache the file data sent. If I remove session_start() the browser caching works as expected respecting the Cache-Control headers sent.

    I don't quite understand why this is the case since I compared the output of readfile() with and without session_start() before it and the output seems to be the same.

    For the record I'm using PHP 5.5.