2010-08-11 140 views
6

我们的RESTful API的一部分将允许用户使用序列号注册项目。由于序列号不是全球唯一的,因此它不能用作资源的标识符,所以我们将使用一个POST到父资源,这将生成一个标识符,例如,响应幂等HTTP POST请求

POST /my/items 

<item serial-number="ABCDEF" /> 

在项目尚未注册的情况下,HTTP语义已定义良好。我们返回一个Location标题,并将注册的项目作为实体主体,例如

HTTP 201 Created 
Location: /my/items/1234  

<item id="1234" serial-number="ABCDEF" /> 

但是,在物品已经注册的情况下,API应该是幂等的并且返回先前注册的物品而不创建新物品。我最好的猜测是它应该返回一个200 OK状态代码,并使用Content-Location标头来指示该项目实际来自哪里,例如,

HTTP 200 OK 
Content-Location: /my/items/1234  

<item id="1234" serial-number="ABCDEF" /> 

这是否合理?我并不完全清楚位置或内容位置是否更适合第二种情况。

回答

7

我最近有类似的要求。对于幂等操作PUT是最好的方法。你说得对,外部id和内部id不匹配。我解决它通过外部ID目标创建一个专用的资源:

PUT /api-user/{username}/items/{serialNumber} 

内部我解决它,以防CREATE我的情况下,我做了“用户名”和“ABCDEF”序列号或UPDATE没有项目。

如果它是一个CREATE,我将为UPDATE 200返回201.更多返回的有效负载包含本地ID和外部序列号,就像您在有效负载中所建议的一样。

+0

嗯,其实我喜欢这个。尽管序列号可能不是全球唯一的,但它们在用户范围内是唯一的,几乎有100%的概率,因此它可以作为范围唯一标识符。这也解决了我的问题,设备如何通过在此URL上使用GET来检查它是否已被注册,并检查响应是否为200或404。 – 2010-08-18 09:04:58

1

Here是一个有趣的讨论两个标题的用法。它声称Content-Location没有为PUT或POST定义,所以在你的情况下Location可能是更好的选择。当然不清楚哪个更好。

总的来说,我认为你的方法是有道理的。

+0

该文章缺少一点,它说Content-Location没有为PUT和POST定义,但HTTP规范实际上表示它没有为请求定义,但没有对响应进行任何说明。我认为它可能是正确的,虽然说Content-Location是用于替代形式,而Location是实际位置。从规格难以确定:-S – 2010-08-11 13:37:29