ETag头未返回304

5

我目前正在开发REST API。我想检查HTTP缓存是否正常工作,但不幸的是它根本不起作用。无论我做什么,它总是返回HTTP代码200,而根据我的了解,它应该返回304。

以下是我的PHP代码:

public function getList()
{
    $this->addHeaders(array(
        'Cache-Control' => 'public, must-revalidate, max-age=120',
        'eTag' => 'xyz123',
    ));

    $array = array(
        'foo' => 'bar',
        'nested' => array(
            'lorem' => 'ipsum',
            'dolor' => 'sit amet'
        )
    );

    $this->addHeader('Content-Length', strlen(json_encode($array, true)));

    return new JsonModel($array);
}

响应/请求

enter image description here

ETag并没有改变,所以除了第一次请求之外,后续请求都应从缓存中获取。我错了吗?

我正在遵循这两篇文章:

我也使用了弱验证器- Last-Modified,但我仍然遇到了同样的问题。浏览器在请求中发送了正确的头信息,但我仍然得到了200的响应。


1
你是如何配置eTag处理的?这里有一个回答描述了最小化设置 - Christian Strempfer
1
如果我没记错的话,检查提交的ETag是否与服务器上当前的ETag不同应该是您服务器实现的责任吧?在这种情况下,您的代码需要响应304 - rmoestl
1
我看到你正在使用Apache 2.4。也许你遇到了这里描述的bug:https://dev59.com/questions/eHNA5IYBdhLWcg3wmfK5 - Thiago Curvelo
3个回答

7

ETag需要服务器发送304响应才能触发从缓存加载。

在时间为基础的缓存中:

  1. 客户端发起初始请求,将响应缓存一段时间
  2. 在后续请求中,如果资源在缓存中,则使用缓存而无需与服务器联系以获取该资源

在ETag基础的缓存中:

  1. 客户端发起初始请求,将响应与服务器提供的该资源的ETag一起缓存一段时间
  2. 在后续请求中,如果资源在缓存中,则将ETag包含在新请求中作为If-None-Match字段发送给服务器。
  3. 服务器检查If-None-Match头信息,如果与服务器上的内容匹配,则发送304未修改指令,指示客户端缓存使用其本地副本。如果ETag不同,则服务器正常返回该资源。

要使您的代码工作,您需要在PHP中检查是否存在If-None-Match头信息:

If(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == 'xyz123') {
    header("HTTP/1.1 304 Not Modified");
    exit();
}

3
您的客户端发送了一个值为max-age=0Cache-Control头。这表明客户端请求一个新鲜的响应,服务器发送HTTP 200状态码。
客户端发送的Cache-Control头通常是使用浏览器中的开发者工具并未禁用“禁用缓存”选项的结果。

2
看起来你没有实现检查eTag标头的逻辑。这不能自动发生,因为服务器不理解业务逻辑,因此无法确定何时应该使缓存失效。
还有另一个答案,描述了minimal setup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接