Cache Headers on PHP file not working - php

I have an application where a number of otherwise static javascript files are being generated via PHP to allow configuration options to alter the static files (path like: mystaticfile.js.php). Everything works fine EXCEPT that I can't seem to get the cache settings to work and these resources are being reloaded with every page load.
The PHP file uses the following headers to try to set the cache settings:
$expires= 60 * 60 * 24 * 60; //cache for 60 days
header('Pragma: public');
header('Cache-Control: max-age=' . $expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
header("content-type: application/x-javascript");
However, when the files are served they're showing headers that look like:
HTTP/1.1 200 OK
Date: Sun, 06 Nov 2016 19:18:00 GMT
Server: Apache/2.2.15 (CentOS)
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 744
Keep-Alive: timeout=15, max=95
Connection: Keep-Alive
Content-Type: application/x-javascript
My first thought was that it was that it might be because Apache has the ExpiresActive flag set on but I don't see any ExpiresByType rules set for PHP files.
Reading online it sounds like ETag issues could be the problem, but I've added
Header unset Pragma
FileETag None
Header unset ETag
to the http.conf file (and restarted the service) and still no dice.
Any thoughts?

Source: PHP: Worry about some magical added “Cache-Control” Header ?
These headers are automatically set by the PHP Session module to
prevent browser/proxy based caching of your pages. Depending on your
environment setup, it’s possible to control these headers by using the
session_cache_limiter() function or use the php.ini
To disable these behaviour just pass an empty string to the
session_cache_limiter() function as mentioned in the documentation:
session_cache_limiter('');

Related

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.
Expires: Thu, 19 Nov 1981 08:52:00 GMT could be the cause. Technically if the Cache-Control header has a max-age directive then Expires should be ignored (Ref : https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires). However it is worth checking by removing that header.
Your PHP code is not setting it. So I assume it is coming from some common config / code which gets executed on every outgoing response. Have you put this in your Nginx config for all PHP requests?
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.

Trouble downloading Excel files all of a sudden

I'm all of a sudden having a hard time downloading excel spreadsheets from our webserver.
We use apache2.2.22 and php 5.4.45-0+deb7u7.
The files are corrupt after download.
I've verified the spreadsheet files are OK. (I'm able to open them w/o problem if I don't download them via the browser then try to look at them.)
Here's the response header:
Cache-Control no-store, no-cache, must-reval…te, post-check=0, pre-check=0
Connection Keep-Alive
Content-Encoding gzip
Content-Length 22
Content-Type text/html
Date Mon, 29 Jan 2018 17:56:52 GMT
Expires Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive timeout=3, max=100
Pragma no-cache
Server Apache/2.2.22 (Debian)
Vary Accept-Encoding
X-Powered-By PHP/5.4.45-0+deb7u7
I'm just totally stumped here.
I've also been trying to add a mime-type like this:
case "xlsx":
header("Content-type: application/vnd.ms-excel-xml");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // use 'attachment' to force a download
break;
Nothing seems to be working. (but it used to work flawlessly.)
Any help or ideas come much appreciated. Thank you.

set expire headers through PHP

We are rendering minified css / js through php with following expire headers
header('Expires:'.gmdate('D, d M Y H:i:s', 1407595380 + 3600 * 24 * 90).' GMT');
header('Cache-Control: public');
header('Last-Modified: 1407595380');
header('Content-type: text/css');
Response headers we are getting mentioned in-line
Cache-Control public
Connection Keep-Alive
Content-Encoding gzip
Content-Length 3224
Content-Type text/css
Date Mon, 11 Aug 2014 14:54:55 GMT
Expires Fri, 07 Nov 2014 14:43:00 GMT
Keep-Alive timeout=5, max=100
Last-Modified 1407595380
Pragma no-cache
Server Apache/2.2.22 (Ubuntu)
But every time i refresh my page , browser gives me 200 response code instead of 304. Browser is not using own cache for php generated minified files and rest css js having 304 code on subsequent requests.
Thanks
$timeToCache = 3600 * 24 * 90;
header('Expires:'.gmdate('D, d M Y H:i:s', 1407595380 + $timeToCache).' GMT');
header('Cache-Control: public');
header('Cache-Control: max-age='.$timeToCache);
header('Last-Modified: 1407595380');
header('Content-type: text/css');
header('Pragma: cache');
Pragma: no-cache might give you clue.
Although it is for legacy HTTP/1.0, Try setting Pragma: cache .

PHP file download with mod-xsendfile does not download entire file

I am having problem serving downloads from our website. Large files just won't download in full. Download will stop somewhere in between... Example this file (size cca 172MB) won't download in full size (there are other files also).
I switched from entirely PHP-base download script, the one included in Kohana framework:
return download::force($filePath);
to a mod-xsendfile solution. I was reading about the possible problems with PHP based download scripts and large file and cam over mod-xsendfile is the right solution... Well looks like not, I am getting the same result with both techniques. My current download implementation using mod-xsendfile headers like this:
header("X-Sendfile: $filePath");
header("Content-type: application/octet-stream");
header('Content-Disposition: attachment; filename="' . basename($filePath) . '"');
What am I doing wrong?
UPDATE:
I used this HTTP sniffer to check response headers and this is the result if it helps solving this problem.
Status: HTTP/1.1 200 OK
Server: Apache
Set-Cookie: dewesoftsession=63ms5j67kc231pr4bpm8cmg1f7; expires=Sat, 30-Mar-2013 11:36:59 GMT; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: dewesoftsession=63ms5j67kc231pr4bpm8cmg1f7; expires=Sat, 30-Mar-2013 11:36:59 GMT; path=/
Content-Disposition: attachment; filename="DEWESoft_FULL_7_0_5.exe"
Last-Modified: Mon, 24 Sep 2012 12:50:12 GMT
ETag: "25814de-ac291e9-4ca7207c7fcd9"
Content-Type: application/octet-stream
Content-Length: 180523497
Date: Sat, 30 Mar 2013 09:37:01 GMT
X-Varnish: 294312007
Age: 2
Via: 1.1 varnish
Connection: close
X-Varnish-Cache: MISS
After couple of days we managed to find what cause the problem. Varnish has a start-up parameter called send_timeout which is set to 600s by default. With large file downloads you might run into this timeout which will cause your download to be interrupted.
So increasing Varnish's send_timeout parameter will help you solve this kind of issue.

sending cache-control headers not working in Codeigniter

I'm probably missing something obvious, but my Codeigniter app is not sending headers when I ask it to.
So in any controller or the extended MY_Controller:
$this->output->set_header("Last-Modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT");
$this->output->set_header("Expires: " . gmdate( "D, j M Y H:i:s", time() ) . " GMT");
$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate");
$this->output->set_header("Cache-Control: post-check=0, pre-check=0");
$this->output->set_header("Pragma: no-cache");
$this->output->set_header("Steve: it aint working you know");
And the headers I get are:
HTTP/1.1 200 OK
Date: Mon, 19 Mar 2012 18:03:06 GMT
Server: Apache/2.2.20 (Ubuntu)
X-Powered-By: PHP/5.3.6-13ubuntu3.6
Last-Modified: Mon, 19 Mar 2012 18:03:06 GMT
Expires: Sat, 01 Jan 2000 00:00:01 GMT
Cache-Control: post-check=0, pre-check=0, max-age=0
Pragma: no-cache
Steve: it aint working you know
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 10780
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
So I know it's sending headers from the Steve: header but it's not sending my Cache-Control settings. If I comment out the Cache-Control setting, it still displays the same value.
Where could this be being overridden? Is it Codeigniter, PHP or Apache?
I would check your Apache config, particularly how mod_expires and the Header Directive are configured.
Note that the "header is modified just after the content handler and output filters are run, allowing outgoing headers to be modified." So Apache may be set to modify the headers you've set in PHP.
I'm no Apache expert, but this is what I had to work with to fix a similar issue.
Steps I took:
added the following to my .htaccess file.
<IfModule mod_headers.c>
Header add Cache-Control: "no-store, no-cache, must-revalidate"
</IfModule>
ran
sudo a2enmod headers
sudo service apache2 restart

Categories