REST API 设计 - PUT 请求的资源关系和幂等性:完整的资源表示究竟意味着什么?

REST API Design - Resource relationships and Idempotency of a PUT request: What, exactly, is meant by a full resource representation?

我了解对于部分更新,必须采取非幂等的操作。为此,一种有效的方法是向该资源发出 POST 请求。

我对相关资源有疑问。例如,假设以下资源及其属性:

  1. 帐户
    编号
    姓名
    帐号#
    用户(合集)

  2. 用户
    编号
    姓名

现在假设我想对帐户进行部分更新 - 例如,更改帐户名称。

我可以提出以下请求作为有效的部分更新:

POST /account/id/123

{
    "name" : "My New Name"
}

我的问题是关于一个完整的 PUT 请求,它 必须是幂等的并且必须包含资源的完整表示

我可以将以下操作作为有效的幂等请求吗?

PUT /account/id/123

{
    "name" : "My New Name",
    "accountNumber" : "654-345-4323"
}

这是否被视为有效的幂等操作?我已经包括了所有顶级 "Account" 信息,但我质疑它,因为我没有 post 属于该帐户的所有 USERS

为了成为一个有效的幂等请求,我是否需要在 PUT 请求中也包含它的所有子资源?

如果要将PUT请求设计为完整的资源替换,那么这意味着您还需要为资源的所有可分配(可编辑)属性赋值,包括资源的关系(链接) .否则,未设置的属性被视为设置为 null.

对于部分请求,您可以使用 PATCH HTTP 方法。还有一个 PUT 约定,如果您的资源表示足够简单,可以使用部分更新。

PATCH vs. PUT

引用:

PATCH vs. PUT

The HTTP RFC specifies that PUT must take a full new resource representation as the request entity. This means that if for example only certain attributes are provided, those should be remove (i.e. set to null).

An additional method called PATCH has been proposed recently. The semantics of this call are like PUT inthat it updates a resource, but unlike PUT, it applies a delta rather than replacing the entire resource. At the time of writing, PATCH was still a proposed standard waiting final approval.

For simple resource representations, the difference is often not important, and many APIs simply implement PUT as a synonym for PATCH. This usually doesn’t give any problems because it is not very common that you need to set an attribute to null, and if you need to, you can always explicitly include it.

However for more complex representations, especially including lists, it becomes very important to be able to express accurately the changes you want to make. Therefore, it is my recommendation now to both provide PATCH and PUT, and make PATCH do an relative update and have PUT replace the entire resource.

It is important to realize that the request entity to PATCH is of a different content-type that the entity that it is modifying. Instead of being a full resource, it is a resource that describes modifications to be made to a resource. For a JSON data model, which is what this essay is advocating, I believe that there are two sensible ways to define the patch format.

  1. An informal approach where you accept a dict with a partial representation of the object. Only attributes that are present are updated. Attributes that are not present are left alone. This approach is simple, but it has the drawback that if the resource has a complex internal structure e.g. containing a big list of dicts, then that entire list of dicts need to be given in the entity. Effectively PATCH becomes similar to PUT again.
  2. A more formal approach would be to accept a list of modifications. Each modification can be a dict specifying the JSON path of the node to modify, the modification (‘add’, ‘remove’, ‘change’) and the new value.

一个更容易理解的方法是考虑PUT方法忽略目标资源的当前状态,所以"full resource representation"意味着它必须有所有数据需要用新资源替换现有资源。

在您的示例中,这可能是没有用户的帐户的有效完整表示。

当某些东西丢失时,服务器采用默认值是没问题的,但应该正确记录,因为一些用户可能会混淆部分更新。