我的HTTP条件实现是否可以在PHP中获得答案? [英] Is my implementation of HTTP Conditional Get answers in PHP is OK?

查看:94
本文介绍了我的HTTP条件实现是否可以在PHP中获得答案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



为了快速回顾一下,我在每个页面可缓存的内容上都是这样做的:

  session_cache_limiter( '公共'); //缓存客户端和代理
session_cache_expire(180); // 3小时
header('Content-Type:'。$ documentMimeType。'; charset ='。$ charset);
header('ETag:''。$ eTag。''); // $ eTag是$ currentLanguage + $ lastModified
的MD5如果($ isXML)
header('Vary:Accept'); // $ documentMimeType可以是XHTML的application / xhtml + xml或text / html(基于$ _SERVER ['HTTP_ACCEPT'])
header('Last-Modified:'。$ lastModified);
header('Content-Language:'。$ currentLanguage);

另外,每个页面都有自己的URL(适用于各种语言)。例如,index.php将以英文的URL/ en / home和法文的/ fr / accueil提供。 我的大问题是从HTTP请求仅在需要时回答304未修改以if-none-match和if-modified。

doc我发现是:
http://rithiur.anthd.com/tutorials /conditionalget.php

这就是我所做的实现(这段代码在可缓存的页面上称为ASAP): p>

  $ 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)
{
// if if-none-match and if-modified-since已收到。
//它们必须匹配文档值才能发送HTTP 304答案。
if($ ifNoneMatch == $ eTag&& $ ifModifiedSince == $ lastModified)
{
header('Not Modified',true,304);
exit();
}
}
else
{
//只收到一个头,它与文档值匹配,发送一个HTTP 304答案。
if(($ ifNoneMatch!== false& $ amp; $ ifNoneMatch == $ eTag)||($ ifModifiedSince!== false&& $ ifModifiedSince == $ lastModified))
{
header('Not Modified',true,304);
exit();


我的问题有两个:




  • 这是否是正确的方法?我的意思是,当if-none-match和if-modified-since发送时,两者必须匹配以回答304,并且如果只发送两个中的一个,则只匹配此发送即可发送一个304?

  • 当在这里描述的上下文中使用时,这2个片段是否是公共缓存友好的(我的意思是缓存对代理 Web浏览器友好) / li>


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



编辑:增加赏金...我期待高质量的答案。如果您在猜测某事,请不要回答/投票! 这不完全正确。请查看算法: alt text http://img532.imageshack.us/img532 /1017/cache.png

  • 解决方案代理友好,您可以使用Cache-control:proxy-revalidate来强制缓存服从您提供的任何新鲜度信息资源(仅适用于共享代理缓存)



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



    $

     函数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-

    你绝对可以同时设置。但是:

    lockquote

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



    RFC2616#14.26

    示例值(W代表'weak';详细信息请参阅 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:*

    特殊情况下,值* 匹配资源的任何当前实体。


    After searching a lot, reading every tutorials I've found and asking some questions here, I've finally managed to answer corrctly (at least I think) to if-none-match and if-modified-since HTTP requests.

    To do a quick recap, this is what I do on every pages cacheable:

    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);
    

    Also, every page have it's own URL (for every languages). For example, "index.php" will be served under URL "/en/home" in English and "/fr/accueil" in French.

    My big problem was to answer a "304 Not Modified" to if-none-match and if-modified-since HTTP requests only when needed.

    The best doc I've found is: http://rithiur.anthd.com/tutorials/conditionalget.php

    And this is the implementation I did of it (this piece of code is called ASAP on pages that can be cached):

    $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();
        }
    }
    

    My question is two fold:

    • Is it the correct way to do it? I mean when if-none-match and if-modified-since are sent, both must match to answer a 304, and if only one of the two is sent, only matching this one is OK to send a 304?
    • When used in the context described here, is these 2 snippets are public cache friendly (I mean cache friendly on proxies and Web browsers)?

    BTW, I use PHP 5.1.0+ only (I don't support versions lower that that).

    Edit: Added bounty... I expect quality answer. Don't answer/vote if you are guessing something!

    解决方案

    • It's not quite correct. Please take a look at the algorithm: alt text http://img532.imageshack.us/img532/1017/cache.png
    • The solution is proxy-friendly, you may use Cache-control: proxy-revalidate to force caches to obey any freshness information you give them about a resource (only applies to shared|proxy caches)

    Here is the function that might help:

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

    I suggest that you take a look at the following article: http://www.peej.co.uk/articles/http-caching.html

    Update:

    [AlexV] Is is even possible to receive if-none-match AND if-modified-since at the same time?

    You can definitely have both set. However:

    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.

    RFC2616 #14.26

    Example values (W stands for 'weak'; read more in 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: *
    

    As a special case, the value "*" matches any current entity of the resource.

    这篇关于我的HTTP条件实现是否可以在PHP中获得答案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆