Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Caching HTTP responses when they are dynamically created by PHP

I think my question seems pretty casual but bear with me as it gets interesting (at least for me :)).

Consider a PHP page that its purpose is to read a requested file from filesystem and echo it as the response. Now the question is how to enable cache for this page? The thing to point out is that the files can be pretty huge and enabling the cache is to save the client from downloading the same content again and again.

The ideal strategy would be using the "If-None-Match" request header and "ETag" response header in order to implement a reverse proxy cache system. Even though I know this far, I'm not sure if this is possible or what should I return as response in order to implement this technique!

like image 688
Mehran Avatar asked May 15 '12 07:05

Mehran


People also ask

Which caching is available in PHP?

PHP basically has two main types of caching: 'output caching' and 'parser caching'. PHP 'output caching' saves a chunk of data somewhere that can later be read by another script faster than it can generate it. 'Parser caching' is specific feature.

Do PHP files get cached?

They are caching the output of PHP programs, apparently to avoid running the PHP code, and sending that whenever user(s) at a particular IP address request the page.

What is HTTP response cache?

android.net.http.HttpResponseCache. Caches HTTP and HTTPS responses to the filesystem so they may be reused, saving time and bandwidth. This class supports HttpURLConnection and HttpsURLConnection ; there is no platform-provided cache for DefaultHttpClient or AndroidHttpClient .


1 Answers

Serving huge or many auxiliary files with PHP is not exactly what it's made for.

Instead, look at X-accel for nginx, X-Sendfile for Lighttpd or mod_xsendfile for Apache.

The initial request gets handled by PHP, but once the download file has been determined it sets a few headers to indicate that the server should handle the file sending, after which the PHP process is freed up to serve something else.

You can then use the web server to configure the caching for you.

Static generated content

If your content is generated from PHP and particularly expensive to create, you could write the output to a local file and apply the above method again.

If you can't write to a local file or don't want to, you can use HTTP response headers to control caching:

Expires: <absolute date in the future>
Cache-Control: public, max-age=<relative time in seconds since request>

This will cause clients to cache the page contents until it expires or when a user forces a page reload (e.g. press F5).

Dynamic generated content

For dynamic content you want the browser to ping you every time, but only send the page contents if there's something new. You can accomplish this by setting a few other response headers:

ETag: <hash of the contents>
Last-Modified: <absolute date of last contents change>

When the browser pings your script again, they will add the following request headers respectively:

If-None-Match: <hash of the contents that you sent last time>
If-Modified-Since: <absolute date of last contents change>

The ETag is mostly used to reduce network traffic as in some cases, to know the contents hash, you first have to calculate it.

The Last-Modified is the easiest to apply if you have local file caches (files have a modification date). A simple condition makes it work:

if (!file_exists('cache.txt') || 
    filemtime('cache.txt') > strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    // update cache file and send back contents as usual (+ cache headers)
} else {
    header('HTTP/1.0 304 Not modified');
}

If you can't do file caches, you can still use ETag to determine whether the contents have changed meanwhile.

like image 166
Ja͢ck Avatar answered Oct 08 '22 05:10

Ja͢ck