考虑以下情况:
现有两个实体:shopping card #1
和item #1
。我想将item #1
添加到shopping card #1
。有两种方法可以设计Restful api
:
1 没有身体:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
Host: myshoppingsite.com
2:使用正文(包含实体):
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
Host: myshoppingsite.com
{itemId: "1"}
实际上,我无法确定哪一个更好,而且在休息方面更有意义。有什么想法吗?
(注意:我认为http方法应该是PUT
因为幂等性,但这不是我的问题。)
PS:我对第一个设计的问题是请求中没有此类enclosed entity
。语言上的put是一个及物动词,所以我希望有人put
s 某事。我认为同样的故事不知何故在HTTP世界中。
答案 0 :(得分:1)
PUT
是一个HTTP动词,应该创建或替换目标URI,因此这会使您的第一个选项立即出错。此请求应替换所有购物车中的商品:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/
由于您想添加某些东西到您的购物车,这不是一个选项。这实际上留下了两个选择。第一:共同的:
POST http://myshoppingsite.com/api/shoppingcards/1/items/
POST
可能意味着许多事情,但在REST服务的上下文中,它通常用于将某些内容附加到集合中。但是,你提到你想要幂等。这里有两个选项,首先你可以仍然使用POST
,并且在API的上下文中保证请求 是幂等的。使用POST
并不意味着它的每个定义都是非幂等的,它只是意味着仅仅HTTP规范并不能保证它。这并不妨碍你使请求具有幂等性。
另一个选项确实是PUT
:
PUT http://myshoppingsite.com/api/shoppingcards/1/items/1
您对此有疑虑,因为在API的上下文中,您说请求正文最终会为空。
这样做的原因是你在网址的最后/1
附加了特殊内容,我觉得这有什么不对。如果您想遵循REST最佳实践,那么网址不应该有任何特殊含义。
我认为,如果你坚持使用PUT
,那么做一个更健全的方法就是摆脱“一个id”的概念。该概念仅存在于您的数据库中,不应该进入API。
相反,我认为您的服务有一个产品列表,例如:
http://myshoppingsite.com/products/1
要使用PUT
将商品添加到购物车,此请求可能如下所示:
PUT http://myshoppingsite/api/shoppingcards/1/items/[completely-arbitrary-string-or-perhaps-a-uuid]
Content-Type: application/json
{
"product" : "http://myshoppingsite.com/products/1",
"quantity" : 5
}
就个人而言,我只会使用POST
。
问:应该有关于您添加的产品的一些信息,不是吗?是的,该信息是Uril的一部分。为什么不好?
我不是说这很糟糕,我说这不是RESTful。拿起任何关于REST的书,你会看到这个确认。这也许是开始阅读有关REST的更多内容的好地方:
http://martinfowler.com/articles/richardsonMaturityModel.html
我个人会说,很少有人构建真正的RESTful服务。这就是为什么我还要特别指出我不想说这对你的特定API是坏的或好的,它根本就不是RESTful。
如果我不关心这些原则并希望保留我的特殊意义网址计划怎么办?
那是一个公平的观点,但是我们已经超越了原来的问题了。如果你想设计一个API,其中网址的最后一位实际上是购物车中商品的“表示”,那么我同意在主体中也是多余的。< / p>
在那种情况下,我会说,保持请求体空。我猜是不要把它称为REST。