假设我需要为客户创建货件,并且该货件需要一个地址。两个资源都需要创建。
在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
}
}
答案 0 :(得分:2)
首先要考虑业务和可用性的影响,然后使用RESTful设计实践来实现合理的解决方案。
在您的示例中,如果您仅为创建货件和嵌入地址实施单独的REST调用,则应用程序开发人员将无法以原子方式创建货件。如果装运的创建成功,然后创建地址失败或网络连接丢失,则最终会在后端发送不完整的数据。即使应用程序开发人员能够回滚更改,您也会为应用程序设计增加显着的复杂性。
因此,对于创建,我会允许将地址包含在货件中,或者如果没有地址的货件违反您的业务规则,则强制将其包括在内。其他决策(无论是创建单独的更新调用还是同时更新所有货件字段或支持两者),业务规则和应用程序设计通常也会建议。
答案 1 :(得分:1)
这只是我的意见。但我会允许这两种方法。要做到这一点,我会使用两种不同的媒体类型。但是,如果您仅使用application/json
媒体类型,则仍然允许这两种媒体类型。
大多数语言都有automatic de/serializers
从json
到模型对象并返回。但是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一无所知的开发人员如何完成用例。最常见的答案将显示最佳方法。