Handling If-Modified-Since Header in a PHP-Script

Handling If-modified-since header in a PHP-script

This is definitely possible in PHP!

When the browser checks if there were modifications, it sends an If-Modified-Since header; in PHP this value would be set inside $_SERVER['HTTP_IF_MODIFIED_SINCE'].

To decode the date/time value (encoded using rfc822 I believe), you can just use strtotime(), so:

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($localFileName))
{
header('HTTP/1.0 304 Not Modified');
exit;
}

Explanation: if the If-Modified-Since header is sent by the browser AND the date/time is at least the modified date of the file you're serving, you write the "304 Not Modified" header and stop.

Otherwise, the script continues as per normal.

How to test for If-Modified-Since HTTP Header support

I have performed some testing on this and it appears to work as follows;

If you send an If-Modified-Since header with a date that is in the past (5 mins previous to the current time should do it) then sites such as google.com, w3.org, mattcutts.com will return a "HTTP/1.1 304 Not Modified" header. Sites such as yahoo.com, bbc.co.uk and stackoverflow.com always return a "HTTP/1.1 200 OK".

The "Last-Modified" header has nothing to do with "If-Modified-Since" because the whole point of sending back a "HTTP/1.1 304 Not Modified" header is that you don't have to send the body with it (thus saving bandwidth - which is the whole point behind this).

Therefore, the answer to my question is that if a site doesn't return a "HTTP/1.1 304 Not Modified" header when you send an "If-Modified-Since 5 mins ago" header, the site doesn't support the "If-Modified-Since" request properly.

If I am incorrect, please say so and provide testing to show.

Edit: I forgot to add that a good test is to make a normal HEAD request to the domain (e.g. w3.org), grab the "Last Modified" date and then make another request with "If-Modified-Since:". This will test that both the "Last Modified" value and "If-Modified-Since" request are supported. Please Note: just because the server sends back a "Last Modified" date doesn't mean it supports "If-Modified-Since"

If Modified Since Header in WordPress

the_modified_date() is a template tag that must used inside the loop, that is why it is not wokring for you.

WordPress provide a action and filter hook to include or modify HTTP headers:

  • send_headers action
  • wp_headers filter (I don't find reference in codex)

But it doesn't work for this purpose. For example, the next code is not working:

add_action( 'send_headers', 'cyb_add_last_modified_header' );
function cyb_add_last_modified_header() {
//Check if we are in a single post of any type (archive pages has not modified date)
if( is_singular() ) {
$post_id = get_queried_object_id();
if( $post_id ) {
header("Last-Modified: " . get_the_modified_time("D, d M Y H:i:s", $post_id) );
}
}
}

Why?

The main wp query is not build at this moment, neither in wp_headers filter. So, is_singular() returns false, get_queried_object_id() returns NULL and there is no way to get the modified time of the current post.

A posible solution is to use template_redirect action hook, as suggested by Otto in this question (tested and working):

add_action('template_redirect', 'cyb_add_last_modified_header');
function cyb_add_last_modified_header($headers) {

//Check if we are in a single post of any type (archive pages has not modified date)
if( is_singular() ) {
$post_id = get_queried_object_id();
if( $post_id ) {
header("Last-Modified: " . get_the_modified_time("D, d M Y H:i:s", $post_id) );
}
}

}

Please Note

The question is answered by @cybmeta at here. I'm just sharing the answer here so that if anyone is looking for the answer here, he/she will find it. All credit goes to @cybmeta.

Caching image requests through PHP - If-Modified-Since not being sent

I believe it should be

if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $file_time)) {

Checking if the modified time is greater than or equal rather than just equal. Although I do understand the two values should be the same.

Answering HTTP_IF_MODIFIED_SINCE and HTTP_IF_NONE_MATCH in PHP

I've always used:

function caching_headers ($file, $timestamp) {
$gmt_mtime = gmdate('r', $timestamp);
header('ETag: "'.md5($timestamp.$file).'"');
header('Last-Modified: '.$gmt_mtime);
header('Cache-Control: public');

if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmt_mtime || str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == md5($timestamp.$file)) {
header('HTTP/1.1 304 Not Modified');
exit();
}
}
}

Don't remember whether I wrote it or got it from somewhere else...

I'm normally using it at the top of a file in this way:

caching_headers ($_SERVER['SCRIPT_FILENAME'], filemtime($_SERVER['SCRIPT_FILENAME']));


Related Topics



Leave a reply



Submit