Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使PHP页面返回“;“304未修改”;如果没有';没有修改_Php_Apache_Caching_Http Status Codes - Fatal编程技术网

使PHP页面返回“;“304未修改”;如果没有';没有修改

使PHP页面返回“;“304未修改”;如果没有';没有修改,php,apache,caching,http-status-codes,Php,Apache,Caching,Http Status Codes,我有一个PHP文件,每次都会返回相同的东西和相同的$\u GET参数,这是确定性的 不幸的是,出于效率考虑(该文件经常被请求),每当请求PHP页面时,Apache默认为“200OK”响应,这使得用户再次下载该文件 当且仅当参数相同时,是否有任何方法发送304未修改标题 奖金: 我可以为它设置一个过期时间吗?这样,如果缓存的页面超过(比如)三天,它就会发送一个“200 OK”响应。您是否尝试过标题(“HTTP/1.0 304未修改”)在您的PHP代码中被调用?如果不熟悉,在开始向缓冲区输出任何内容

我有一个PHP文件,每次都会返回相同的东西和相同的$\u GET参数,这是确定性的

不幸的是,出于效率考虑(该文件经常被请求),每当请求PHP页面时,Apache默认为“200OK”响应,这使得用户再次下载该文件

当且仅当参数相同时,是否有任何方法发送
304未修改
标题

奖金:
我可以为它设置一个过期时间吗?这样,如果缓存的页面超过(比如)三天,它就会发送一个“200 OK”响应。

您是否尝试过
标题(“HTTP/1.0 304未修改”)
在您的PHP代码中被调用?如果不熟悉,在开始向缓冲区输出任何内容之前,您将希望将其放入代码中


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

Header("HTTP/1.1 304 Not Modified");
exit();
然而,光靠这一点是不够的

问题是,您不知道如何请求该文件,因此需要浏览器的配合

如果在传入请求中修改了
,则可以查找
,如果存在并且在日期范围内,则返回相应的状态代码

如果在最初生成PHP时发送一个适当的
Expires
头,那么浏览器或代理缓存可能会决定根本不获取请求(尽管更可能的情况是,如果从
头修改,他们会设置
)。如果没有
Expires
标题,浏览器可能总是会重新尝试完整请求

有关更多信息,请参阅并搜索“14.25”


浏览器将把
GET
参数映射到缓存副本,顺便说一句。你不需要在那里做任何工作。

如果你自己不缓存页面(或者至少是它的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;
?>

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


您还可以使用
HTTP\u进行修改,因为
更易于控制

此脚本将再次呈现整个PHP脚本,但在此之后,它将检查ETag ist是否与输出字符串的MD5等效,如果等效,则发送304,并且不使用bandwith。 您还可以使用所有查询字符串等的MD5创建这样的东西,并将其存储在某个地方,您不需要重新创建输出内容(甚至更快)


每次访问脚本时都应该调用我?这似乎是我的一般想法。不过对于OP来说,不需要缓存任何内容。根据他的条件,他可以根据id计算一个Etag。是的,实际的实现可以是简单的,也可以是复杂的。试图说明这一点,但我陷入了提供一个实现的陷阱,md5()覆盖了内容,不应该存在:P
function sanitize_output($buffer) {
    $headers = apache_request_headers();
    $tt5=md5($buffer);  
    header('ETag: '.$tt5);
    if (isset($headers['If-None-Match']) && $headers['If-None-Match']===$tt5) {
        header('HTTP/1.1 304 Not Modified');
        header('Connection: close');
        exit();
    }
    return $buffer;
}

ob_start("sanitize_output");