基于 If-Modified-Since 标头修改 REST API 表示是不是有效?

Posted

技术标签:

【中文标题】基于 If-Modified-Since 标头修改 REST API 表示是不是有效?【英文标题】:Is it valid to modify a REST API representation based on a If-Modified-Since header?基于 If-Modified-Since 标头修改 REST API 表示是否有效? 【发布时间】:2014-12-09 09:24:40 【问题描述】:

我想在我的 API 中实现“获取更改的值”功能。例如,假设我有以下 REST API 调用:

GET /ws/school/7/student

这将获取学校 #7 中的所有学生。不幸的是,这可能很多。因此,我想修改 API 以仅返回自特定时间以来已修改的学生记录。 (用例是一个夜间进程从另一个系统运行,将所有学生从我的系统拉到他们的系统。)

我看到http://blog.mugunthkumar.com/articles/restful-api-server-doing-it-the-right-way-part-2/ 建议使用 if-modified-since 标头并返回如下表示:

搜索自 if-modified-since 标头中请求的时间以来更新的所有学生 如果有的话,以 200 OK 返回那些学生 如果该查询没有返回学生,则返回 304 Not Modified

我明白他想做什么,但这似乎是错误的做法。 If-Modified-Since 标头 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24) 的定义说:

If-Modified-Since request-header 字段与一种方法一起使用,使其有条件:如果请求的变体自该字段中指定的时间以来没有被修改,则不会从服务器返回实体;相反,将返回 304(未修改)响应而没有任何消息正文。

这对我来说似乎是错误的。我们不会返回 RFC 指示的表示或 304,而是一些混合。看起来客户端代码(或者更糟糕的是,服务器和客户端之间的网络缓存)可能会误解含义并替换本地缓存值,而实际上它应该只是更新它。

那么,两个问题:

这是对标头的正确使用吗? 如果不是(我怀疑不是),最佳做法是什么?查询字符串参数?

【问题讨论】:

【参考方案1】:

这不是标题的正确用法。 If-Modified-Since 标头是 HTTP 客户端(浏览器或代码)在请求资源时可以可选提供给服务器的标头。如果提供,则含义是“我想要资源 X,但前提是它自时间 T 以来已更改”。其目的是允许客户端缓存资源。

您提议的用法的语义是“我想要从时间 T 以来发生的集合 X 的更新”。这是对 X 子集的请求。您的动机似乎不是启用缓存。您的客户端缓存表示似乎包含所有 X,即使典型请求只会返回您对 X 的一小部分更改;也就是说,响应不是您直接缓存的,因此缓存需要在自定义用户逻辑客户端进行。

查询字符串参数是一个更合适的解决方案。在seq 下方会是一个序列号或时间戳

GET /ws/schools/7/students/updates?since=seq

服务器端 我想您从系统开始就有一系列更新,并且上述形式的请求将获取序列值大于seq 的前 N ​​个更新。这样一来,如果客户远远落后并需要赶上,结果就会被分页。

【讨论】:

谢谢你的确认,贝斯手。这也是我的想法。

以上是关于基于 If-Modified-Since 标头修改 REST API 表示是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章

在“If-Modified-Since”HTTP 标头中使用客户端生成的时间

解析 If-Modified-Since 标头 (node.js)

在请求中发送“if-modified-since”标头

了解 If-Modified-Since HTTP 标头

Cloudfront如何每次都避免If-Modified-Since标头请求

Safari 不发送“If-Modified-Since”和“If-None-Match”标头