如果在初始请求中获得资源,什么使条件 GET 成为“有条件的”?

gar*_*mac 2 conditional get restful-authentication http-1.1 http-headers

分解条件 GET 的原因:

RFC 2616它指出GET方法改变为“有条件GET”如果请求消息包括If-*If-Modified-SinceIf-Unmodified-SinceIf-MatchIf-None-Match,或If-Range)头字段。

然后声明:

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

根据我的理解,这是说如果在任何新的后续请求中满足“ ”条件,它只会返回被请求的数据If-*。例如,如果 GET 请求返回一个带有Etag标头的响应,那么下一个请求必须包含If-None-Match带有ETag值以将客户端传回请求的资源。

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

我的问题:

为什么它说明了实体(从请求的资源)将“转移ONLY ”如果If-*条件(在我的例子,其中客户端返回等会见ETag与价值If-None-Match,以缓存所请求的资源),如果资源或者“实体" 是否被返回,有或没有 " If-*" 被返回?它不会“在条件标头描述的情况下”返回资源,因为它返回资源而不管是否返回200 OK304 Not Modified,具体取决于是否If-*返回“ ”标头。我对此有什么误解?

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

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

Vas*_*nov 6

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

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

场景一

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

GET /foo/bar HTTP/1.1
Host: example.com
Run Code Online (Sandbox Code Playgroud)

服务器:给你。

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

Hello world!
Run Code Online (Sandbox Code Playgroud)

(过了一段时间)

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

GET /foo/bar HTTP/1.1
Host: example.com
If-None-Match: "2ac07d4"
Run Code Online (Sandbox Code Playgroud)

服务员:是的,没问题"2ac07d4"。只需从您的缓存中取出它,我不会将其发送给您。

HTTP/1.1 304 Not Modified
Run Code Online (Sandbox Code Playgroud)

场景二

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

GET /foo/bar HTTP/1.1
Host: example.com
Run Code Online (Sandbox Code Playgroud)

服务器:给你。

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

Hello world!
Run Code Online (Sandbox Code Playgroud)

(过了一段时间)

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

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

Hello dear world!
Run Code Online (Sandbox Code Playgroud)

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

HTTP/1.1 204 No Content
ETag: "f6049b9"
Run Code Online (Sandbox Code Playgroud)

(更多的时间过去了)

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

GET /foo/bar HTTP/1.1
Host: example.com
If-None-Match: "2ac07d4"
Run Code Online (Sandbox Code Playgroud)

服务器:对不起,但"2ac07d4"已过时。我们现在有一个新版本,名为"f6049b9". 来,我发给你。

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

Hello dear world!
Run Code Online (Sandbox Code Playgroud)

分析

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

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

条件头域是:If-None-Match: "2ac07d4"

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

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

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

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