Link to home
Start Free TrialLog in
Avatar of mychel_normandeau
mychel_normandeauFlag for Canada

asked on

When to answer HTTP if-none-match and if-modified-since with HTTP 304 "Not Modified"

I have cacheable (by proxies and clients) dynamic content made in PHP 5.1.0+.I already send the correct HTTP headers (including Last-Modified and ETag) to clients.

I now want my script to be able to answer $_SERVER['HTTP_IF_MODIFIED_SINCE'] and $_SERVER['HTTP_IF_NONE_MATCH'] when present. When the conditions matches, I want to answer with a HTTP 304 "Not Modified" to clients.

After reading tutorials, RFCs and asking questions, I've implemented a system that I want to validate. My question is: does my system is OK? Am I missing something?

(See code below)

1) The format of $_SERVER['HTTP_IF_NONE_MATCH'] can be either:

a) If-None-Match: "abc", "def", "ghi"

b) If-None-Match: "dfgjd"

and NOT:

c) If-None-Match: "abc, def, ghi"

2) As soon as one ETag in HTTP_IF_NONE_MATCH match one of the current document ETag, I issue a "304 Not Modified" even if HTTP_IF_MODIFIED_SINCE is missing or if HTTP_IF_MODIFIED_SINCE don't match the last modified date of the document.

3) If HTTP_IF_NONE_MATCH is missing but HTTP_IF_MODIFIED_SINCE is there and matching the document last modified date, I issue a "304 Not Modified".

4) To recap (using code): 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).
function anyTagMatched()
{
    global $currentPageETags; //array()

    $ifNoneMatch = array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) ? explode(',', $_SERVER['HTTP_IF_NONE_MATCH']) : false;
    if ($ifNoneMatch === false)
        return NULL;

    foreach ($ifNoneMatch as $currETag)
    {
        $currETag = StripQuotes(trim($currETag));
        if ($currETag != '' && in_array($currETag, $currentPageETags))
            return true;
    }

    return false;
}

function isExpired()
{
    global $currentPageLastModified;

    $ifModifiedSince = array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;
    if ($ifModifiedSince === false)
        return true;
    else
        return $ifModifiedSince != $currentPageLastModified;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of VanHackman
VanHackman
Flag of El Salvador image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial