問題描述
經(jīng)過大量搜索、閱讀我找到的每個教程并在這里提出一些問題后,我終于設(shè)法正確地(至少我認(rèn)為)回答了 if-none-match 和 if-modified-since HTTP 請求.
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);
此外,每個頁面都有自己的 URL(對于每種語言).例如,index.php"將在英文網(wǎng)址/en/home"和法文網(wǎng)址/fr/accueil"下提供.
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.
我的大問題是僅在需要時對 if-none-match 和 if-modified-since HTTP 請求響應(yīng)304 Not Modified".
My big problem was to answer a "304 Not Modified" to if-none-match and if-modified-since HTTP requests only when needed.
我找到的最好的文檔是:http://rithiur.anthd.com/tutorials/conditionalget.php
The best doc I've found is: http://rithiur.anthd.com/tutorials/conditionalget.php
這是我做的實現(xiàn)(這段代碼在可以緩存的頁面上稱為ASAP):
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();
}
}
我的問題有兩個:
- 這是正確的做法嗎?我的意思是,當(dāng)發(fā)送 if-none-match 和 if-modified-since 時,both 必須匹配才能回答 304,如果只發(fā)送兩者之一,則只匹配這個就可以發(fā)送304?
- 在此處描述的上下文中使用時,這 2 個代碼段是否對公共緩存友好(我的意思是在代理和網(wǎng)絡(luò)瀏覽器上對緩存友好)?
- 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)?
順便說一句,我只使用 PHP 5.1.0+(我不支持低于它的版本).
BTW, I use PHP 5.1.0+ only (I don't support versions lower that that).
增加了賞金……我期待高質(zhì)量的回答.如果您在猜測某事,請不要回答/投票!
Added bounty... I expect quality answer. Don't answer/vote if you are guessing something!
推薦答案
- 這不太正確.請看一下算法:alt text http://img532.imageshack.us/img532/1017/cache.png
- 該解決方案是代理友好的,您可以使用 Cache-control: proxy-revalidate 強制緩存遵守您提供的有關(guān)資源的任何新鮮信息(僅適用于共享|代理緩存)
以下是可能有用的函數(shù):
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
) ) ;
}
我建議你看看下面的文章:http://www.peej.co.uk/articles/http-caching.html
I suggest that you take a look at the following article: http://www.peej.co.uk/articles/http-caching.html
更新:
[AlexV] 甚至可以同時接收 if-none-match 和 if-modified-since 嗎?
[AlexV] Is is even possible to receive if-none-match AND if-modified-since at the same time?
你絕對可以同時設(shè)置.然而:
You can definitely have both set. However:
如果沒有實體標(biāo)簽匹配,那么服務(wù)器可以執(zhí)行請求的方法,就好像 If-None-Match 頭字段不存在一樣,但也必須忽略任何 If-Modified-Since 頭字段中的要求.也就是說,如果沒有實體標(biāo)簽匹配,則服務(wù)器不得返回 304(未修改)響應(yīng).
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
示例值(W 代表弱";閱讀更多內(nèi)容RFC2616 #13.3.3):
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: *
作為一種特殊情況,值*"匹配資源的任何當(dāng)前實體.
As a special case, the value "*" matches any current entity of the resource.
這篇關(guān)于我在 PHP 中實現(xiàn)的 HTTP 條件獲取答案是否可以?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!