浏览器是否应该自动处理304响应?

时间:2018-04-10 10:28:47

标签: http caching browser etag http-status-code-304

可能是一个愚蠢的问题,但我还没有找到任何明确的答案。

我的服务器处理ETag缓存以获取我们拥有的一些非常大的JSON响应,如果304 NOT MODIFIED标头包含与新生成的(浅ETag)相同的哈希,则返回If-None-Match空主体。 / p>

浏览器是否应该自动处理,或者异步使用API​​的浏览器内客户端应用程序需要实现一些逻辑来处理此类响应(即如果304被响应则使用缓存版本,创建/更新否则缓存版本??

因为到目前为止,我已经手动实现了这个逻辑客户端,但我想知道我是否只是重新设计了方形轮......

换句话说,例如,使用Cache-Control标头,浏览器内的客户端应用程序不需要解析该值,例如检查max-age,以某种方式存储它,设置超时等:一切都由浏览器直接处理。问题是:浏览器在收到304时会表现出相同的行为吗?

以下是我到目前为止编写客户端的方法(使用AngularJS构建,在浏览器中运行):

myModule

  .factory("MyRepository", ($http) => {

    return {
      fetch: (etag) => {
        return $http.get(
          "/api/endpoint",
          etag ? { headers: { "If-None-Match": etag } } : undefined
        );
      }
    };

  })

  .factory("MyService", (MyRepository, $q) => {

    let latestEtag = null;
    let latestVersion = null;

    return {
      fetch: () => {
        return MyRepository
          .fetch(latestEtag)
          .then((response) => {
            latestEtag = response.headers("ETag");
            latestVersion = response.data;
            return angular.copy(latestVersion);
          })
          .catch((response) => {
            return 304 === error.status
              ? angular.copy(latestVersion)
              : $q.reject(response)
          });
      }
    };

  });

基本上,上述逻辑是否有效需要,或者我应该能够直接使用$http.get("/api/endpoint")

上面的代码工作正常,这似乎意味着它需要以编程方式处理,尽管我从未见过这样的" custom"关于我读过的文章的实现。

2 个答案:

答案 0 :(得分:3)

304响应由浏览器自动处理

所以我创建了一个简单的页面

<html>
<head>
<script src="./axios.min.js"></script>
<script src="./jquery-3.3.1.js"></script>
</head>
<body>
<h1>this is a test</page>
</body>
</html>

并添加了test.json个文件

root@vagrant:/var/www/html# cat test.json
{

"name": "tarun"

}

然后在下面的nginx中添加

location ~*  \.(jpg|jpeg|png|gif|ico|css|js|json)$ {
   expires 365d;
}

现在结果

<强> AXIOS

AXIOS

正如您所看到的,第一个请求是200,第二个请求是304,但对JS代码没有影响

<强>的jQuery

jQuery response

同样适用于jQuery

从卷曲中你可以看到服务器没有在第二个304请求

上发送任何内容
$ curl -v 'http://vm/test.json' -H 'If-None-Match: "5ad71064-17"' -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.9' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://vm/' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' -H 'If-Modified-Since: Wed, 18 Apr 2018 09:31:16 GMT' --compressed
*   Trying 192.168.33.100...
* TCP_NODELAY set
* Connected to vm (192.168.33.100) port 80 (#0)
> GET /test.json HTTP/1.1
> Host: vm
> If-None-Match: "5ad71064-17"
> DNT: 1
> Accept-Encoding: gzip, deflate
> Accept-Language: en-US,en;q=0.9
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
> Accept: */*
> Referer: http://vm/
> X-Requested-With: XMLHttpRequest
> Connection: keep-alive
> If-Modified-Since: Wed, 18 Apr 2018 09:31:16 GMT
>
< HTTP/1.1 304 Not Modified
< Server: nginx
< Date: Wed, 18 Apr 2018 09:42:45 GMT
< Last-Modified: Wed, 18 Apr 2018 09:31:16 GMT
< Connection: keep-alive
< ETag: "5ad71064-17"
<
* Connection #0 to host vm left intact

因此,您无需处理304,浏览器将为您完成这项工作。

答案 1 :(得分:1)

是的,可能所有现代主流浏览器都使用条件请求来处理响应验证。 Mark Nottingham的The State of Browser Caching, Revisited文章的相关摘录:

  

Validation允许缓存与服务器核对,以查看是否可以重用过时的存储响应。

     

所有经过测试的浏览器都支持基于ETagLast-Modified的验证。棘手的部分是确保304 Not Modified响应与存储的响应正确组合;具体而言,304中的标头会更新存储的响应标头。

     

所有经过测试的浏览器都会在304上更新存储的标题,包括立即响应和后续缓存服务。

     

这是个好消息;使用304更新标头是一种重要的机制,当它们不同步时会导致问题。


有关更多信息,请查看Ilya Grigorik的HTTP Caching文章。