My question is about how to reply a HTTP 304 "Not Modified" when I receive both if-none-match and if-modified-since from a proxy/client request.
From RFC 2616 secttion 14.26 ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26 ):
If none of the entity tags match, then the server MAY perform the requested method as if the If-None-Match header field did not exist, but MUST also ignore any If-Modified-Since header field(s) in the request. That is, if no entity tags match, then the server MUST NOT return a 304 (Not Modified) response.
I am not sure to understand this statement...
$_SERVER['HTTP_IF_NONE_MATCH']
vs. my ETags that I sent earlier?$_SERVER['HTTP_IF_NONE_MATCH']
match my ETags, I stop all verifications and serve the page normally. Anyone can translate this RFC part in pseudo-code (or PHP code) and/or answer my 2 points above?
EDIT 1: Thank you St.Woland for your answer. Can you (or anyone else) tell me if I'm correct on these 6 points:
The format of $_SERVER['HTTP_IF_NONE_MATCH']
can be either:
a)If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
b) If-None-Match: "xyzzy"
and NOT:
c) If-None-Match: "xyzzy, r2d2xxxx, c3piozzzz"
If !array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)
, anyTagMatched() returns NULL.
As soon as an ETag in $_SERVER['HTTP_IF_NONE_MATCH']
match my document ETag, anyTagMatched() returns TRUE.
If none of the Etags in $_SERVER['HTTP_IF_NONE_MATCH']
are matching my document ETag, anyTagMatched()
returns FALSE.
If $_SERVER['HTTP_IF_MODIFIED_SINCE']
is set and matches my document "last modified" date isExpired()
returns FALSE, otherwise return TRUE.
As soon as anyTagMatched()
returns TRUE, I issue a 304. If anyTagMatched() returned NULL and isExpired()
returned FALSE I can issue a 304. In any other situation I serve my page as normal (I also issue the up-to-date Last-Modified and ETag headers).
This should be put in the end (moved for better look).
$anyTagMatched = anyTagMatched() ;
if( $anyTagMatched || ( ( null === $anyTagMatched ) && !isExpired() ) ) {
notModified() ;
}
// Output content
Pseudocode (review needed):
<?php
/**
* Calculates eTag for the current resource.
*/
function calculateTag() {
}
/**
* Gets date of the most recent change.
*/
function lastChanged() {
}
/**
* TRUE if any tag matched
* FALSE if none matched
* NULL if header is not specified
*/
function anyTagMatched() {
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) :
false ;
if( false !== $if_none_match ) {
$tags = split( ", ", $if_none_match ) ;
$myTag = calculateTag() ;
foreach( $tags as $tag ) {
if( $tag == $myTag ) return true ;
}
return false ;
}
return null ;
}
function isExpired() {
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
false;
if( false !== $if_modified_since ) {
// Compare time here; pseudocode.
return ( $if_modified_since < lastChanged() ) ;
}
return true ;
}
function notModified() {
header('HTTP/1.0 304 Not Modified');
exit ;
}
Main answer here.