0

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();
}
?>
YOU
  • 120,166
  • 34
  • 186
  • 219
Ameer
  • 978
  • 4
  • 13
  • 34
  • Your code didn't go through. Reattach? – mattbasta Mar 16 '10 at 03:18
  • Error here: http://redbot.org/?uri=http%3A%2F%2Fameer1234567890.co.cc%2Ftest%2Ftest.php – Ameer Mar 16 '10 at 03:41
  • do not add the Content-Length header on 304 responses (ref RFC 2616 sec 4.3) – Hafthor Jun 16 '11 at 22:57
  • @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 Nov 22 '12 at 19:58

3 Answers3

1

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.

Ameer
  • 978
  • 4
  • 13
  • 34
0

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;
    }
}
mattbasta
  • 13,492
  • 9
  • 47
  • 68
  • My issue is not with detecting or returning proper headers, but just about an empty line outputted by php after the headers. – Ameer Mar 16 '10 at 03:30
  • Error here: http://redbot.org/?uri=http%3A%2F%2Fameer1234567890.co.cc%2Ftest%2Ftest.php – Ameer Mar 16 '10 at 03:40
  • Do you have a `register_shudown_function` set? – mattbasta Mar 17 '10 at 12:06
  • I do not have a register_shutdown_function in my code. Could it be set by my webhost. I am using 110mb.com – Ameer Mar 20 '10 at 00:35
  • It could be that you've got some weird whitespace before your opening ` – mattbasta Mar 20 '10 at 04:57
  • My file doesn't have any whitespaces or characters before . I do not have a BOM too and my file is in LF format. As you said, my best suspect is my host. – Ameer Mar 21 '10 at 02:12
0

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']));
?>
Community
  • 1
  • 1
Binyamin
  • 7,493
  • 10
  • 60
  • 82
  • As I mentioned above, my issue is not with detecting or returning proper headers, but just about an empty line outputted by php after the headers. – Ameer Feb 18 '11 at 05:26
  • @Ameer - Maybe use `exit;` instead `exit();`. – Binyamin Feb 18 '11 at 09:53