2010-01-07 16 views
8

經過多次搜索,閱讀我找到的每個教程,並在這裏提出一些問題,終於成功地回答了(至少我認爲)if-none-match和if-modified-自HTTP請求以來。我的HTTP條件實現是否可以在PHP中獲得答案?

做一個快速回顧一下,這是我做的每頁面可緩存:

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沒有修改」if-none-match和if-modified-因爲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發送時,兩個必須匹配才能回答304,並且如果兩個中只有一個被髮送,那麼只匹配這個就可以發送304?
  • 當在這裏所描述的上下文中使用,是這2個片段是公共緩存友好的(我的意思是緩存在代理 Web瀏覽器友好的)?

順便說一句,我只使用PHP 5.1.0+(我不支持更低的版本)。

編輯:添加賞金...我期待高質量的答案。如果你正在猜測某物,不要回答/投票!

回答

22
  • 這是不完全正確。請看一下算法:alt text http://img532.imageshack.us/img532/1017/cache.png
  • 該解決方案是代理友好的,您可以使用Cache-control:proxy-revalidate來強制緩存服從您提供的有關資源的任何新鮮度信息(僅適用於shared | proxy高速緩存)

下面是可能幫助功能:

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-沒有匹配和IF-,因爲修改在同一時間?

你絕對可以同時設置。但是:

如果沒有實體標籤匹配,那麼服務器可以執行請求的方法,就好像如果-None-Match頭字段不存在,而且還必須忽略任何的If-Modified-Since頭場(s)在請求中。也就是說,如果沒有實體標籤匹配,那麼服務器絕不能返回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: * 

作爲一個特殊的情況下,值 「*」 的任何當前實體匹配資源。

+3

還要注意RFC2616(HTTP1.1)規範第14.26節有關If-None-Match語法的內容。這個問題和原始問題都不允許使用多個etag值或「*」。這就是說,這個假設可能是正確的99.9%的時間。 – MZB 2010-01-13 23:01:06

+1

@Mike Bell:是的,我知道ETag可以包含許多值或*,但我不知道任何瀏覽器使用這個...我不知道是否有任何系統實際使用它。順便說一句如何解析ETag時,它超過1值? *在ETag中意味着什麼? – AlexV 2010-01-14 16:18:14

+0

@ St.Woland:我讀過提供的文章,看着你的圖表(很好的工作),它似乎與我的第二個片段中的「其他」部分相對應(對嗎?)。我覺得奇怪的是,如果兩個if-none-match和if-modified-since都被接收到,那麼只有兩個中的一個必須匹配才能回答304 ......甚至可以接收if-none-match AND if修改 - 因爲在同一時間? – AlexV 2010-01-14 16:21:39

相關問題