HTTP中的if-none-match和if-modified-since以及304澄清

时间:2010-01-18 14:40:54

标签: php http caching http-1.1

我的问题是当我从代理/客户端请求收到两者 if-none-match和if-modified-since时,如何回复HTTP 304“Not Modified”。

来自RFC 2616第14.26节(http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26):

  

如果没有任何实体标签匹配,那么   服务器可以执行请求   方法好像是If-None-Match标头   字段不存在,但也必须   忽略任何If-Modified-Since标头   请求中的字段。也就是说,如果   没有实体标签匹配,那么服务器   不得返回304(未修改)   响应。

我不确定理解这句话......

  1. “如果PHP中没有任何实体标签匹配”,他们会说$_SERVER['HTTP_IF_NONE_MATCH']与我之前发送的ETag相比吗?
  2. 如果我正确理解了这句话,只要$_SERVER['HTTP_IF_NONE_MATCH']中列出的所有ETag都没有匹配我的ETag,我就会停止所有验证并正常提供该页面。
  3. 任何人都可以用伪代码(或PHP代码)翻译这个RFC部分和/或回答我的2分以上?

    编辑1: 谢谢St.Woland的回答。你(或其他任何人)可以告诉我,如果我在这6点上是正确的:

    1. $_SERVER['HTTP_IF_NONE_MATCH']的格式可以是:

      a)If-None-Match:“xyzzy”,“r2d2xxxx”,“c3piozzzz”

      b)如果 - 无匹配:“xyzzy”

      和NOT:

      c)如果 - 无匹配:“xyzzy,r2d2xxxx,c3piozzzz”

    2. 如果!array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER),anyTagMatched()返回NULL。

    3. 只要$_SERVER['HTTP_IF_NONE_MATCH']中的ETag与我的文档ETag匹配,anyTagMatched()就会返回TRUE。

    4. 如果$_SERVER['HTTP_IF_NONE_MATCH']中的Etags都没有与我的文档ETag匹配,则anyTagMatched()返回FALSE。

    5. 如果设置了$_SERVER['HTTP_IF_MODIFIED_SINCE']并且我的文档与“上次修改”日期isExpired()匹配,则返回FALSE,否则返回TRUE。

    6. 只要anyTagMatched()返回TRUE,我就发出304.如果anyTagMatched()返回NULL并且isExpired()返回FALSE我可以发出304.在任何其他情况下我都会提供我的页面正常(我也发布最新的Last-Modified和ETag标题)。

1 个答案:

答案 0 :(得分:5)

这应该放在最后(移动以便更好看)。

$anyTagMatched = anyTagMatched() ;
if( $anyTagMatched || ( ( null === $anyTagMatched ) && !isExpired() ) ) {
    notModified() ;
}
// Output content

伪代码(需要审核):

<?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 ;
}

主要答案here