Return the PHP page "304 Not Modified" if it has not been modified

I have a PHP file that will return the same with the same $ _GET parameters every time - it is deterministic.

Unfortunately, for efficiency (this file is requested very often), Apache defaults to "200 OK" whenever a PHP page is requested, forcing the user to download the file again.

Is there a way to send the 304 Not Modified header if and only if the parameters are the same?

Bonus : Can I set the expiration time on it, so if the cached page is longer than, say, three days ago, it sends a β€œ200 OK” response?

+4
source share
4 answers

Without caching the page yourself (or at least its Etag), you cannot use 304. A complete caching algorithm is somewhat beyond the scope, but the general idea:

 <?php function getUrlEtag($url){ //some logic to get an etag, possibly stored in memcached / database / file etc. } function setUrlEtag($url,$etag){ //some logic to get an etag, possibly stored in memcached / database / file etc. } function getPageCache($url,$etag=''){ //[optional]some logic to get the page from cache instead, possibly not even using etag } function setPageCache($url,$content,$etag=''){ //[optional]some logic to save the page to cache, possibly not even using etag } ob_start(); $etag = getUrlEtag($_SERVER['REQUEST_URI']); if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { header("HTTP/1.1 304 Not Modified"); exit; } if(($content=getPageCache($_SERVER['REQUEST_URI'],$etag))!==false){ echo $content; exit; } ?> //the actual page <?php $content = ob_get_clean(); setUrlEtag($_SERVER['REQUEST_URI'],$etag=md5($url.$content)); function setPageCache($_SERVER['REQUEST_URI'],$content,$etag); header("Etag: $etag"); echo $content; ?> 

All common errors: you can not display cache pages for registered users, caching of partial content may be more desirable, you yourself are responsible for preventing obsolete content in the cache (possibly using triggers in the backend or database for modification or just playing with logic getUrlEtag ) etc. etc.

You can also play with HTTP_IF_MODIFIED_SINCE if it is easier to control.

+10
source

Typically, you return HTTP status codes using the header function:

 Header("HTTP/1.1 304 Not Modified"); exit(); 

However, this is not enough.

The problem is that you don’t know how the file requested, so you need a bit of collaboration with the browser.

You can search for If-modified-since headers in the incoming request and return the corresponding status code, if present, and in the date range.

If you send the correct Expires header when you initially generate PHP, then the browser or proxy cache may not receive the request at all (although most likely they will set the If-modified-since header). Without the Expires header, the browser is likely to always repeat the full request.

For more information, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html and find "14.25"

The browser will match the GET parameters with the cached copy, by the way. You do not need to do any work there.

+7
source

Have you tried header("HTTP/1.0 304 Not Modified"); in your PHP code which is being called? If you are unfamiliar, you will want to put this in your code before you start dumping anything.

http://php.net/manual/en/function.header.php

+2
source

This script will display the entire PHP script again, but after that it checks if ETag is equivalent to the MD5 equivalent of the output string, and if so, it sends 304 and no bandwidth is used. You can also create such a thing with MD5 of all QueryString, etc. And save it somewhere, you will not need to recreate the output content (even faster)

 function sanitize_output($buffer) { $headers = apache_request_headers(); $tt5=md5($buffer); header('ETag: '.$tt5); if (isset($headers['If-None-Match']) && $headers['If-None-Match']===$tt5) { header('HTTP/1.1 304 Not Modified'); header('Connection: close'); exit(); } return $buffer; } ob_start("sanitize_output"); 
0
source

Source: https://habr.com/ru/post/1311924/


All Articles