我已经阅读了put-vs-post-in-rest,而且我知道PUT用于创建和更新特定资源,并在URL中明确指定标识符。
但是,如果我要严格更新"更新"使用If-Match操作(这意味着用户必须提供有效的ETag来更新资源),假设PUT也用于创建命名资源(不需要If-Match),那么API将不得不猜测是否PUT request是指根据是否提供If-Match标头来更新或创建。
我知道这可以做到,但我认为这很奇怪。是否有其他(更合理)的方法(通过不使用PUT)?
感谢。
更新
以下是我的情景:
# create the resource the first time
curl -X PUT -d '{"foo": "bar"}' /resource/r_id
# the resource already exists, so this will fail with a 4xx error
curl -X PUT -d '{"foo": "bar2"}' /resource/r_id
# must provide valid If-Match to make updates work
curl -X PUT -H 'If-Modefied: myetag' -d '{"foo": "bar2"}' /resource/r_id
# what makes it confusing is this:
# user want to make a new record, but /resource/r_id2 in fact exists
# the API will return an error message, should it be
# "creation failed -- already exist" or "update failed -- ETag not provided"?
curl -X PUT -d '{"foo": "bar"}' /resource/r_id2
并不是说不能这样做,只是因为我认为这个设计(对于ETag控制的更新和命名创建都有PUT)可能会令人困惑,我个人认为如果我使用不同的词汇(不仅仅是PUT),它会更好,但是,我在这里询问我能做到的合理和RESTful方式是什么。
答案 0 :(得分:2)
您可以使用“If-None-Match:*”保护PUT-to-create,请参阅http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p4-conditional-26.html#rfc.section.3.2.p.7。
此外,您可能需要考虑使用http://greenbytes.de/tech/webdav/rfc6585.html#status-428。
答案 1 :(得分:1)
您可以尝试模仿设计良好的REST API。
对于this feature,CouchDB设计师选择以409 Conflict
作为状态,{"error":"conflict","reason":"Document update conflict."}
作为正文。
Nota bene :删除"文档"当然,因为它是特定的应用程序。
答案 2 :(得分:0)
您不需要使用If-Match限制更新。当您获得PUT时,请检查您的数据存储区。如果具有给定id的资源尚未存在,请创建它。如果是,请将其更新为具有给定值。
If-Match购买的内容是确保资源未在数据存储中更改。你试图避免这种情况:
client 1: GET /resources/1
client 2: GET /resources/1
client 2: PUT /resources/1 with updates
client 1: PUT /resources/1 with updates