0
votes

Sorry for the probably wrong title. I am writing some code to handle If-Modified-Since and If-None-Match requests as part of caching. Everything works perfect except for that PHP returns some content (an empty line) after the headers. The page content should be empty instead. The code that I am using is:

<?php
$lastmod = filemtime($f);
$etag = '"'.dechex($lastmod).'"';
if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $last_mod || $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) {
  header('HTTP/1.1 304 Not Modified');
  header('Content-Length: 0');
  exit();
}
?>
3
Your code didn't go through. Reattach? - mattbasta
Error here: redbot.org/… - Ameer
do not add the Content-Length header on 304 responses (ref RFC 2616 sec 4.3) - Hafthor
@Hafthor - actually it's perfectly fine (if a little stupid) to send a positive content-length with a 304 as the response "is always terminated by the first empty line after the header fields, regardless of the entity-header fields present in the message." See RFC 2616 section 4.4 item 1. - ostergaard

3 Answers

1
votes

Finally solved this bug. Gzip was the culprit. Since I was gzipping the responses to If-Modified-Since and If-None-Match requests too, gzip was adding a few bytes (kind of a gzip header) to the response. Now I have stopped gzipping responses to If-Modified-Since and If-None-Match requests, and it works like a charm.

0
votes

Try this code:

$last_modified = filemtime($f);
if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
    $expected_modified = strtotime(preg_replace('/;.*$/','',$_SERVER["HTTP_IF_MODIFIED_SINCE"]));
    if($last_modified <= $expected_modified) {
        header("HTTP/1.0 304 Not Modified");
        exit;
    }
}
0
votes

I found the solution in Answering HTTP_IF_MODIFIED_SINCE and HTTP_IF_NONE_MATCH in PHP

Create new file caching_headers.php

<?php
function caching_headers($file,$timestamp){
    $gmt_mtime=gmdate('r', $timestamp);
    header('ETag: "'.md5($timestamp.$file).'"');
    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();
        }
    }
    header('Last-Modified: '.$gmt_mtime);
    header('Cache-Control: public');
}
?>

and add this in all php files that you would like to cache:

<?php
include('caching_headers.php');
caching_headers($_SERVER['SCRIPT_FILENAME'],filemtime($_SERVER['SCRIPT_FILENAME']));
?>