2

分解构成条件 GET 的原因:

RFC 2616If-*中,它声明如果请求消息包含( If-Modified-SinceIf-Unmodified-SinceIf-MatchIf-None-MatchIf-Range) 标头字段,则 GET 方法将更改为“条件 GET” 。

然后它说:

条件 GET 方法请求仅在条件头字段描述的情况下传输实体。

据我了解,这意味着只有在任何新的后续请求中满足“ ”条件时,它才会返回所请求的数据。If-*例如,如果 GET 请求返回带有Etag标头的响应,则下一个请求必须包含If-None-Match带有ETag值的 ,以将客户端传输回请求的资源。

ETag但是,如果客户端必须在获取返回的“ ”标头(以返回)之前发送初始请求,If-None-Match那么他们已经拥有请求的资源。因此,任何将来返回If-None-Match带有该ETag值的标头的请求仅指示返回所请求的值,返回200 OK(如果客户端未从初始请求返回If-None-Matchand 值)或304 Not Modified(如果返回),其中通过缓存资源来帮助客户端和服务器。ETag

我的问题:

为什么它声明实体(来自请求的资源)将在满足条件时“传输” (例如在我的示例中,客户端返回带有 an 的值以缓存请求的资源)如果资源或“实体" 是否被返回,是否返回 " "?它不会“在条件标头描述的情况下”返回资源,因为它返回资源尽管返回200 OK304 Not Modified取决于是否返回“”标头。我对此有什么误解?If-*ETagIf-None-MatchIf-*If-*

来自RFC 2616的完整条件 GET 参考:

如果请求消息包含 If-Modified-Since、If-Unmodified-Since、If-Match、If-None-Match 或 If-Range 头字段,则 GET 方法的语义更改为“条件 GET”。条件 GET 方法请求仅在条件头字段描述的情况下传输实体。条件 GET 方法旨在通过允许刷新缓存的实体而不需要多个请求或传输客户端已经持有的数据来减少不必要的网络使用。

4

1 回答 1

7

首先,请注意 RFC 2616 已过时,您应该参考RFC 7232

很难看出究竟是什么让你感到困惑。所以让我用例子来说明。

方案 1

客户A:我需要http://example.com/foo/bar

GET /foo/bar HTTP/1.1
Host: example.com

服务器:给你。

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12
ETag: "2ac07d4"

Hello world!

(一段时间过去了)

客户A:我又需要http://example.com/foo/bar了。但是我的缓存中已经有了这个"2ac07d4"版本。也许那会做?

GET /foo/bar HTTP/1.1
Host: example.com
If-None-Match: "2ac07d4"

服务器:是的,"2ac07d4"很好。只是从你的缓存中取出它,我不会将它发送给你。

HTTP/1.1 304 Not Modified

方案 2

客户A:我需要http://example.com/foo/bar

GET /foo/bar HTTP/1.1
Host: example.com

服务器:给你。

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12
ETag: "2ac07d4"

Hello world!

(一段时间过去了)

客户 B:我想上传新版本的http://example.com/foo/bar.

PUT /foo/bar HTTP/1.1
Content-Type: text/plain
Content-Length: 17

Hello dear world!

服务器:这看起来不错,我正在保存它。我将调用这个版本"f6049b9"

HTTP/1.1 204 No Content
ETag: "f6049b9"

(更多的时间过去了)

客户A:我又需要http://example.com/foo/bar了。但是我的缓存中已经有了这个"2ac07d4"版本。也许那会做?

GET /foo/bar HTTP/1.1
Host: example.com
If-None-Match: "2ac07d4"

服务器:对不起,"2ac07d4"已经过时了。我们现在有一个新版本,它叫做"f6049b9". 来,我发给你。

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 17
ETag: "f6049b9"

Hello dear world!

分析

条件 GET 方法请求仅在条件头字段描述的情况下传输实体。

考虑客户端 A 的第二个请求(在这两种情况下)。

条件头字段是:If-None-Match: "2ac07d4".

它描述的情况是:“资源的选定表示与实体标签不匹配"2ac07d4"”。

场景 1:情况成立,因为资源的选定表示(包含 的表示Hello world!)确实与 entity-tag 匹配"2ac07d4"。因此,根据协议,服务器不会其响应中传输实体。

场景 2:情况确实成立:资源的选定表示(包含 的表示Hello dear world!)与实体标签不匹配"2ac07d4"(而是匹配"f6049b9")。因此,根据协议,服务器确实在其响应中传输实体。

无论如何,服务器是如何提出这些"2ac07d4""f6049b9"?当然,这取决于应用程序,但一种直接的方法是计算实体主体的哈希值(例如 SHA-1)——即使引入很小的更改,该值也会发生巨大变化。

于 2015-11-12T23:31:03.060 回答