针对"相关"资源的REST设计

Fro*_*its 6 rest api-design

假设我有一个拥有多个帐户的客户.实际上任何与另一个复杂对象具有"1对多"关系的数据对象都可以.

一个例子可能是:

{ id: 1, name: "Bob", accounts: [ { id: 2, name: "Work account" }, { id: 3, name: "Home account" } }

我的问题是,何时将帐户作为客户的子资源公开,而不是作为单独的资源?或两者?

例如,我的第一个直觉就是:/customers/1返回上面的对象.如果您想修改其中一个帐户,则必须这样POST/accounts/2.

另一种方法(我在一些API中看到)是暴露另一个路由/customers/1/accounts,它将返回上面的数组,然后在那里设置POST/ PATCH路由以允许API用户改变帐户数组.

我对这种方法的问题在于,如果帐户数组实际上是"通过引用包含",那么REST路由是否正在修改帐户或者仅仅是修改客户与帐户之间的链接还不是很清楚.

这里有最好的做法吗?

小智 5

这是一个很好的问题,尚待讨论(没有“正确”答案)。您可能需要考虑以下几点:

  1. 将子帐户资源嵌入客户资源中将导致总是通过/ customers / {id}请求发送回更多数据。

  2. 如果子帐户资源既非基本客户信息,又需要帐户信息,则非嵌入式子帐户资源将要求客户端发送多个HTTP请求。

  3. 您将要确定确切的安全范例如何与嵌入式资源一起使用。(即是否有可能被允许获取客户的信息,但是不被允许查看客户的账户?)

  4. 在您的域中拥有没有客户的帐户是否有意义?帐户可以转让所有权吗?如果不是这样,那么/ customers / {id} / accounts / {acct_id}更有意义。

隐含在REST的定义中,在URI上发出HTTP方法正在修改URI标识的资源,因此默认情况下,您始终在修改帐户,而不是在客户和帐户之间建立联系。

如果您需要修改帐户链接的功能,则可以发明一种资源,例如“帐户链接请求”(POST / accounts / {id} / linkreqeust或类似性质的东西)。该请求可能具有其自身的状态,在该状态下,您将具有后端功能,该功能将评估该请求,然后确定是否应将帐户与客户链接或从客户分离,然后执行附加/分离过程。

总而言之,REST中没有任何东西可以阻止您使用不同的链接(/ accounts / {id}; / customers / {id} / accounts / {acct_id})引用同一资源。我的偏好是,如果拥有子资源没有安全隐患,那么可以将其与端点结合使用以自行访问子资源。如果帐户可以绑定到多个用户(或没有客户),我还将公开/ accounts / {id}端点。

ex. /customers/1:

{
  "id": "1",
  "name": "John Doe",
  "accounts": {
    "collection": [
      {
        "id": "1",
        "type": "savings",
        "balance": "$400",
        "links": {
          "self": "/customers/1/accounts/1"
        }
      },
      {
        "id": "2",
        "type": "checking",
        "balance": "$600",
        "links": {
          "self": "/customers/1/accounts/2",
          "detach" : "/customers/1/accounts/2/linkrequest?action=detach"
        }
      }
    ],
    "links": {
      "self": "/customers/1/accounts",
      "attach": "customers/1/accounts/linkrequest?action=attach"
    }
  },
  "links": {
    "self": "/customers/1"
  }
}
Run Code Online (Sandbox Code Playgroud)