我可以将 E-tag 用于用户特定的 REST API 以避免每次都发回相同的数据吗?

Can I use E-tag for a user specific REST API in order to not send the same data back every time?

假设我们有一个 API 可以检索用户特定的数据。 出于某种原因,我不希望服务器每次都将数据发送回客户端,因为数据没有改变。

例如,我有一个移动应用程序。每次启动时,它都会显示本地缓存中的数据,但也会在后台从服务器中检索一些用户特定的数据。 我想做的是希望如果数据不变,服务器可以return 304。

E-tag 似乎可以做这种事情,但我不确定它是否是一个好的选择,因为它是特定于用户的 API。

HTTP 是一种 request/response 协议。对于客户端发送的每个请求,服务器都会做出响应。响应可以是失败案例,也可以是成功案例。除非网络掉线,否则永远不会出现服务器不响应的情况!

ETag 通常是资源当前状态的哈希值或预定义的字符串值,即版本计数器的哈希值(正如 Evert 正确提到的那样)在响应中作为 HTTP header 返回,以便客户端可以在它想要更改该特定状态并且不希望服务器在该资源同时被修改时更新它的场景中使用它(=乐观锁定)。

使用 ETag 的第二种情况是检查客户端的状态是否仍然是服务器已知的当前状态,服务器根据资源是否仍然具有 304 Not Modified or a 412 Precondition failed response 响应是否具有相同的 ETag 值。理想情况下,您应该向服务器发出 HEAD 请求,以尽量减少来回发送的负载,因为您可能感兴趣的是客户端已知的当前版本是否仍然是服务器持有的版本。

... but I am not sure if it is a good choice here since it is a user-specific API.

... I read some articles about E-tag but they all didn't mention anything about user-specific data. ...

正如 Jim Webber 指出的那样,HTTP 的核心只是一种传输协议,其领域是通过 Web 传输文档。您最好将其视为文档管理系统,您可以在其中将新文件放置到某个位置,删除或检索它们,或者通过 POST 请求根据服务器自己的语义处理它们。 HTTP 只是基本的。因此,任何遵守 HTTP 规则的 HTTP 客户端都能够使用 RFC 7232 中指定的条件请求,HTTP 服务器也应该如此。因此,无论数据是来自某些 HTTP Web 服务器还是某些 API 由某些 Java、.Net 或任何中间件或框架支持,只要它们遵守相同的 HTTP 协议,都没有区别。不幸的是,一个特定的框架或实现是否支持那种“功能”,如果你愿意的话,那就是另一回事了。

关于使用条件请求是否是一个好的选择,您有哪些选择?如果客户端想知道它是否具有资源的 most-recent 状态,它要么需要礼貌地询问服务器客户端知道的版本是否仍然是最新版本,要么只是(再次)检索整个状态。有些人可能会争辩说,在版本因其他客户端的中间更新而不同的情况下,需要交换多条消息。这是一个有效的论点,尽管您需要估计哪个可能更频繁地发生。在客户端很少检查其版本是否仍然是 most-current 的情况下,或者各种客户端经常对该资源进行更新的情况下,可能再次检索该资源的整个状态可能会减少总共交换的字节数并且因此最终效率更高一些。尽管 HTTP 提供 HEAD requests,您可以利用它来最小化客户端和服务器之间交换的负载大小,因为 HTTP 将 HEAD 定义为

... the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data ...

A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. (Source)

本质上,HEAD 请求和对此类请求的响应仅包含 HTTP headers 但没有进一步的消息 body 这有助于降低交换消息的字节大小显著地。在最好的情况下,当两个版本相同时,您可以显着减少交换的字节数。在最坏的情况下,如果它们不同,额外的开销可能可以忽略不计,除非你真的在 high-performance 边缘笼中。因此,如果您对您当前对某些资源的了解是否仍然是 most-recent 感兴趣,通过 HEAD 的条件请求是 IMO 的一个不错的选择。