创建REST资源:撰写还是分开?

时间:2014-01-17 20:11:12

标签: rest restful-architecture api-design

假设我需要为客户创建货件,并且该货件需要一个地址。两个资源都需要创建。

在REST设计中,首选哪种方法?为什么?

# One request that in-lines the address.
POST /shipments    
{
  "shipment": {
    "customer_id": 1,
    "address": {
      "city": "Toronto",
      ...
    }
  }
}

VS

# Two requests, first creating the address, then passing an id.
POST /addresses
{
  "address": {
    "customer_id": 1,
    "city": "Toronto",
    ...
  }
}

POST /shipment
{
  "shipment": {
    customer_id: 1,
    address_id: 100
  }
}

4 个答案:

答案 0 :(得分:2)

首先要考虑业务和可用性的影响,然后使用RESTful设计实践来实现合理的解决方案。

在您的示例中,如果您仅为创建货件和嵌入地址实施单独的REST调用,则应用程序开发人员将无法以原子方式创建货件。如果装运的创建成功,然后创建地址失败或网络连接丢失,则最终会在后端发送不完整的数据。即使应用程序开发人员能够回滚更改,您也会为应用程序设计增加显着的复杂性。

因此,对于创建,我会允许将地址包含在货件中,或者如果没有地址的货件违反您的业务规则,则强制将其包括在内。其他决策(无论是创建单独的更新调用还是同时更新所有货件字段或支持两者),业务规则和应用程序设计通常也会建议。

答案 1 :(得分:1)

这只是我的意见。但我会允许这两种方法。要做到这一点,我会使用两种不同的媒体类型。但是,如果您仅使用application/json媒体类型,则仍然允许这两种媒体类型。

大多数语言都有automatic de/serializersjson到模型对象并返回。但是YMMV。

尽管这两种媒体类型方法是可选的并且具有重大意义(因为您需要为所有表示而不是application/json使用特定媒体类型),我更喜欢明确。它允许尽早丢弃请求(标头首先到达服务器和客户端)。

但是,如果你问是否有任何“首选”的方式,它不是AFAIK。一个可以为您(或客户端)保存请求和网络往返,但另一个会更清楚地说明您的API结构。

答案 2 :(得分:0)

根据您的描述,您希望操纵/管理两个“REST”资源:货件和地址。

此外,您暗示该地址是货件下的子资源

用例-1:创建包含地址信息的货件

POST /shipments/
BODY: {address {<<address info}}
RETURN: {shipment-id}

用例2:创建没有地址信息的货件

POST /shipments/
BODY: {}
RETURN: {shipment-id}

用例3:更新包含地址信息的货件

PUT /shipments/[shipment-id]/address/
BODY: {address {<<address info}}

用例4:如果您有独立创建地址的用例,则可以

POST /addresses/
BODY: {address-info}
RETURN: {address-id}

用例5:您可以使用地址ID

更新货件
PUT /shipments/[shipment-id]/address/
BODY: {address–id {id-} }

答案 3 :(得分:0)

我相信任何现代公共API(假设您的API是公开的)设计应该来自最常见的用例,而不是来自代码的内部结构。即您的API应尽可能用于该用例。可测试性和内部结构也很重要,但可用性更重要,因为开发人员(实际上是您的服务的客户)对API的易用性比内部复杂设计更加困扰。

因此,我认为,除非您为API提供一组最常见的用例,否则无法为您的问题提供某些答案。然后,您应该考虑询问对您的API一无所知的开发人员如何完成用例。最常见的答案将显示最佳方法。