我正在构建RESTful数据存储并利用条件GET和PUT。在条件PUT期间,客户端可以在资源上包含来自先前GET的Etag,并且如果当前表示与服务器不匹配,则将返回HTTP状态代码412(前提条件失败)。请注意,这是一个基于Atom的服务器/协议。
我的问题是,当我返回412状态时,我是否还可以包含资源的新表示形式,还是用户必须发出新的GET? HTTP规范似乎没有说是或否,Atom规范也没有(尽管它们的示例在响应中显示了一个空的实体主体)。如果不返回新的表示并使客户端专门获取它,这似乎是非常浪费的。想法?
答案 0 :(得分:3)
不,技术上你不应该。错误代码通常用于指定出错的地方。虽然没有什么可以阻止你返回内容(事实上,像404这样的错误会返回一个漂亮的页面,上面写着你没找到你要找的东西),但是响应的重点不是返回其他内容,而是返回一些告诉你错误的东西。从技术上讲,你也不应该返回那些数据,因为你通过了If-None-Match:etag(我假设那是你通过的那个?)
另一方面,你真的需要优化一个额外的http电话吗?
我越是想到这一点,我就越相信这是一个坏主意 - 你是否会在任何其他错误上返回内容? PUT语义是PUT。 GET语义应该用于GET。
答案 1 :(得分:3)
尽管条件GET和PUT被概括为“条件请求”,但它们在概念上是非常不同的。条件GET是性能优化,条件PUT是并发控制机制。很难一起讨论它们。
关于条件GET的问题:如果发送GET并包含If-None-Match标头,则服务器将发送200 Ok(如果资源已更改)和304 Not Modified(如果没有)(如果条件失败)。 412仅用于条件PUT。
更新:我似乎略微误读了这个问题。关于在失败的条件PUT上对本地副本进行“刷新”的观点:可能是缓存已经具有最新版本,并且刷新-GET将从某个缓存提供。让服务器使用412返回当前实体可能实际上会给你带来更差的性能。
答案 2 :(得分:2)
如果由于更新冲突后的额外请求而产生的额外请求数量足以让您产生性能问题,那么我建议您可能会遇到资源粒度问题。
您是否真的希望每天有数百万次用户同时编辑同一资源?也许您需要将delta更改存储到资源中,而不是直接更新资源。如果这些资源真的存在争议,那么用户就不会经常处理过时的数据。
如果您的问题是您的资源包含上次修改日期和最后修改过的用户,并且您必须在每次PUT后执行GET,那么我会更加确信需要扭曲规则。
但是,我认为额外请求的性能损失对于客户端开发人员的清晰度是值得的。