如果资源是在初始请求中获得的,那么条件 GET "conditional" 是什么?

What makes conditional GETs "conditional" if the resource is obtained in the initial request?

分解条件 GET 的内容:

RFC 2616 中指出,如果请求消息包含 If-*If-Modified-SinceIf-Unmodified-SinceIf-MatchIf-None-MatchIf-Range) header 字段。

然后说:

A conditional GET method requests that the entity be transferred ONLY under the circumstances described by the conditional header field(s).

根据我的理解,这是说如果条件满足任何新的“If-*”,它只会return被请求的数据后续请求。例如,如果 GET 请求 return 的响应带有 Etag header,则下一个请求必须包含 If-None-MatchETag 值才能传输客户端返回请求的资源。

但是,如果客户端必须在获得 returned“ETag”header(至 return 和 If-None-Match 之前发送初始请求) 那么他们已经拥有请求的资源。因此,任何将来 return If-None-Match header 与 ETag 值的请求仅指示请求值的 return,returning 200 OK(如果客户端没有 return 来自初始请求的 If-None-MatchETag 值)或 304 Not Modified(如果有的话),这可以通过缓存资源来帮助客户端和服务器。

我的问题:

为什么它声明实体(来自请求的资源)将“被转移" 如果满足 If-* 条件(就像在我的示例中,客户端 return 的 ETag 值带有 If-None-Match 以便缓存请求的资源)如果资源或“entity”被return编辑,有或没有“If-*”被return编辑?它不是 return 资源“ 在条件 header 描述的情况下,因为它 returns 资源尽管 returning 200 OK304 Not Modified 取决于是否“If-*” header 是 returned。我对此有什么误解?

来自 RFC 2616 的完整条件 GET 引用:

The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the client.

首先,请注意 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!

分析

A conditional GET method requests that the entity be transferred ONLY under the circumstances described by the conditional header field(s).

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

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

其描述的情况是:“资源的选定表示不匹配entity-tag "2ac07d4"”。

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

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

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