【问题标题】:Is my implementation of HTTP Conditional Get answers in PHP is OK?我在 PHP 中执行 HTTP Conditional Get answers 是否可以?
【发布时间】:2010-01-07 16:32:50
【问题描述】:

经过大量搜索,阅读了我找到的每个教程并在这里提出了一些问题,我终于成功地(至少我认为)正确回答了 if-none-match 和 if-modified-since HTTP 请求。

简要回顾一下,这是我对每个可缓存页面所做的:

session_cache_limiter('public'); //Cache on clients and proxies
session_cache_expire(180); //3 hours
header('Content-Type: ' . $documentMimeType . '; charset=' . $charset);
header('ETag: "' . $eTag . '"'); //$eTag is a MD5 of $currentLanguage + $lastModified
if ($isXML)
    header('Vary: Accept'); //$documentMimeType can be either application/xhtml+xml or text/html for XHTML (based on $_SERVER['HTTP_ACCEPT'])
header('Last-Modified: ' . $lastModified);
header('Content-Language: ' . $currentLanguage);

此外,每个页面都有自己的 URL(适用于每种语言)。例如,“index.php”将在英文的 URL“/en/home”和法语的“/fr/accueil”下提供。

我的大问题是仅在需要时回答“304 Not Modified”到 if-none-match 和 if-modified-since HTTP 请求。

我找到的最好的文档是: http://rithiur.anthd.com/tutorials/conditionalget.php

这是我对它的实现(这段代码在可以缓存的页面上被称为 ASAP):

$ifNoneMatch = array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false;
$ifModifiedSince = array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false;

if ($ifNoneMatch !== false && $ifModifiedSince !== false)
{
    //Both if-none-match and if-modified-since were received.
    //They must match the document values in order to send a HTTP 304 answer.
    if ($ifNoneMatch == $eTag && $ifModifiedSince == $lastModified)
    {
        header('Not Modified', true, 304);
        exit();
    }
}
else
{
    //Only one header received, it it match the document value, send a HTTP 304 answer.
    if (($ifNoneMatch !== false && $ifNoneMatch == $eTag) || ($ifModifiedSince !== false && $ifModifiedSince == $lastModified))
    {
        header('Not Modified', true, 304);
        exit();
    }
}

我的问题有两个:

  • 这是正确的方法吗?我的意思是当发送 if-none-match 和 if-modified-since 时,both 必须匹配才能回答 304,如果只发送两者之一,则仅匹配此一个即可发送304?
  • 在此处描述的上下文中使用时,这 2 个 sn-ps 是否对公共缓存友好(我的意思是代理 Web 浏览器上的缓存友好)?

顺便说一句,我只使用 PHP 5.1.0+(我不支持低于该版本的版本)。

编辑:增加赏金...我希望得到高质量的答案。如果您猜到了什么,请不要回答/投票!

【问题讨论】:

    标签: php http caching header http-headers


    【解决方案1】:

    以下是可能有帮助的功能:

    function isModified($mtime, $etag) {
        return !( (
            isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
            && 
            strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mtime
        ) || (
            isset($_SERVER['HTTP_IF_NONE_MATCH'])
            && 
            $_SERVER['HTTP_IF_NONE_MATCH'] == $etag
        ) ) ;
    }
    

    我建议你看看下面的文章:http://www.peej.co.uk/articles/http-caching.html

    更新:

    [AlexV] 甚至可以同时接收 if-none-match 和 if-modified-since 吗?

    你绝对可以同时设置。然而:

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

    RFC2616 #14.26

    示例值(W 代表“弱”;在RFC2616 #13.3.3 中了解更多信息):

    If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"
    If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"
    If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    If-None-Match: *
    

    作为一种特殊情况,值“*”匹配资源的任何当前实体。

    【讨论】:

    • 还要注意 RFC2616 (HTTP1.1) 规范第 14.26 节关于 If-None-Match 的语法。这和原始问题都不允许多个 etag 值或“*”。话虽如此,这个假设在 99.9% 的情况下可能是正确的。
    • @Mike Bell:是的,我知道 ETag 可以包含许多值或 ​​ 但我还不知道有任何浏览器使用它......我想知道是否有任何系统实际使用它。顺便说一句,当超过 1 个值时如何解析 ETag? ETag 中的 * 是什么意思?
    • @St.Woland:我阅读了提供的文章并查看了您的图表(干得好),它似乎与我的第二个 sn-p 中的“其他”部分相对应(对吗?) .我对此感到奇怪的是,当同时收到 if-none-match 和 if-modified-since 时,只有 2 个中的 1 个必须匹配才能回复 304... 甚至有可能收到 if-none-match AND if -modified-since 同时?
    • @AlexV:你绝对可以同时设置。我更新了答案,因为评论太多了。
    • 我希望缓存代理能够呈现多个 ETag 值,以适应不同的标头组合。
    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2021-12-18
    • 2014-12-20
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多