4

我正在设计一个 REST API,我想知道处理资源更新的推荐方法是什么。更具体地说,我将允许通过PUT资源上的 a 进行更新,但我应该在PUT请求正文中允许什么?

  1. 总是资源的完整结构?
  2. 总是资源结构的子部分(改变的)?
  3. 两者的结合?

例如,获取资源http://example.org/api/v1/dogs/packs/p1。此资源上的 AGET将提供以下内容:

Request:
GET http://example.org/api/v1/dogs/packs/p1
Accept: application/xml

Response:
<pack>
  <owner>David</owner>
  <dogs>
    <dog>
      <name>Woofer</name>
      <breed>Basset Hound</breed>
    </dog>
    <dog>
      <name>Mr. Bones</name>
      <breed>Basset Hound</breed>
    </dog>
  </dogs>
</pack>

假设我想在包中添加一只狗(嗅探巴吉度猎犬),我是否支持:

Request:
PUT http://example.org/api/v1/dogs/packs/p1
<dog>
  <name>Sniffers</name>
  <breed>Basset Hound</breed>
</dog>

Response:
HTTP/1.1 200 OK

或者

Request:
PUT http://example.org/api/v1/dogs/packs/p1
<pack>
  <owner>David</owner>
  <dogs>
    <dog>
      <name>Woofer</name>
      <breed>Basset Hound</breed>
    </dog>
    <dog>
      <name>Mr. Bones</name>
      <breed>Basset Hound</breed>
    </dog>
    <dog>
      <name>Sniffers</name>
      <breed>Basset Hound</breed>
    </dog>
  </dogs>
</pack>

Response:
HTTP/1.1 200 OK

或两者?如果建议通过结构的子部分支持更新,我将如何处理删除(例如当狗死时)?通过查询参数?

4

2 回答 2

8

是的,始终发送资源的完整表示。否则,您将(根据 PUT 的常见定义和用法)仅用这只狗替换包。

但是,您可能需要考虑以下事项:

  • 在 URL 路径之外使用 XML 命名空间或其他版本控制方式(例如 ?version=2)
  • 将要添加的狗发布到 /dogs/packs/p1。POST 根据定义创建了一个从属资源,因此会将狗添加到包中。
  • 稍微翻新一下您的网址。在我看来,你真的想要 /dogs/1234、/dogs/1235 等等,然后是 /packs/p1、/packs/p2。然后你也可以简单地 POST<dog id="1">到包。

请记住,REST 要求您正确识别资源。包实际上并不是狗的附属资源,每只狗都应该有某种唯一标识符。然后,当访问 /packs/p1/1234 时,您可能希望重定向到 /dogs/1234。或者,或者,尽管接受将下级资源发布到相应的包,但您根本不会使该 URL 可用。

我想得越多,POST 方法就越有意义。也许你甚至可以为所有的狗提供一个 /packs/p1/dogs/ 资源,与包分开。然后,您可以将所有者信息等内容放入 /packs/p1,通过 /packs/p1/dogs/ 获取所有狗的列表(其中应包含包中每只狗的URL列表,例如 /packs/p1 /dogs/1234,见HATEOAS),通过 POST 到 /packs/p1/dogs/ 将新狗添加到包中,并通过删除 /packs/p1/dogs/1235 删除狗。每只狗都可以是完整的表示,甚至可能重定向到 /dogs/1234 等,或者在此包的上下文中狗的不同表示,但再次带有指向“完整”狗的链接。取决于你想如何代表一只狗,这当然也会影响实际发布到 /packs/p1/dogs/ 的内容。Full dog 感觉不对,应该只是我上面显示的一个 ID,也许还有与包关系有关的其他数据。

于 2010-04-27T09:56:14.040 回答
2

PUT 的效果是“替换”。所以,是的,您需要通过 PUT 请求提供完整的表示。

如果您只想更新部分资源,您有以下选择:

  • 定义一个代表零件的资源并放在那里
  • 对子资源使用 POST 并让服务器返回 303 See Other 并带有指向主资源的 Location 标头
  • 使用补丁

在您的情况下,最好将狗作为子资源(狗的集合)并以通常的 POST-as-append 方式发布到该资源

于 2010-04-27T09:42:07.293 回答