如果尚未修改PHP页面,则返回"304 Not Modified"

Chr*_*ann 5 php apache caching http-status-codes

我有一个PHP文件,每次都会返回相同的$ _GET参数 - 这是确定性的.

不幸的是,为了提高效率(经常请求此文件),每当请求PHP页面时,Apache默认为"200 OK"响应,使用户再次下载文件.

当且仅当参数相同时,有没有办法发送304 Not Modified标头?

额外奖励:我可以设置一个到期时间,这样如果缓存的页面超过三天,它会发送"200 OK"响应吗?

Wri*_*ken 10

如果没有自己缓存页面(或者至少是它的Etag),你就无法真正使用304.一个完整的缓存算法有点超出了范围,但总体思路是:

<?php 
function getUrlEtag($url){
    //some logic to get an etag, possibly stored in memcached / database / file etc.
}
function setUrlEtag($url,$etag){
    //some logic to get an etag, possibly stored in memcached / database / file etc.
}
function getPageCache($url,$etag=''){
    //[optional]some logic to get the page from cache instead, possibly not even using etag
}
function setPageCache($url,$content,$etag=''){
    //[optional]some logic to save the page to cache, possibly not even using etag
}
ob_start();
$etag = getUrlEtag($_SERVER['REQUEST_URI']);
if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { 
    header("HTTP/1.1 304 Not Modified"); 
    exit; 
}
if(($content=getPageCache($_SERVER['REQUEST_URI'],$etag))!==false){
    echo $content;
    exit;
}
?>
//the actual page
<?php
$content = ob_get_clean();
setUrlEtag($_SERVER['REQUEST_URI'],$etag=md5($url.$content));
function setPageCache($_SERVER['REQUEST_URI'],$content,$etag);
header("Etag: $etag");
echo $content;
?>
Run Code Online (Sandbox Code Playgroud)

所有常见的陷阱都适用:您可能无法为登录用户显示缓存页面,可能更希望缓存部分内容,您自己负责防止缓存中的陈旧内容(可能在后端使用触发器或在修改时使用数据库,或者只是玩弄getUrlEtag逻辑)等等.

HTTP_IF_MODIFIED_SINCE如果这更容易控制,你也可以玩.


Jon*_*tte 7

通常,您使用Header函数返回HTTP状态代码:

Header("HTTP/1.1 304 Not Modified");
exit();
Run Code Online (Sandbox Code Playgroud)

然而,仅凭这一点是不够的.

问题是你不知道如何请求文件,所以你需要一些浏览器合作.

您可以If-modified-since在传入请求中查找标头,并返回相应的状态代码(如果存在且位于日期范围内).

如果您Expires在最初生成PHP时发送了正确的标头,那么浏览器或代理缓存可能决定根本不提取请求(尽管更可能的是,它们会设置If-modified-since标头).如果没有Expires标题,浏览器可能会始终重新尝试完整请求.

有关更多信息,请参阅http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html并搜索"14.25"

浏览器将GET参数映射到缓存副本btw.你不需要在那里做任何工作.