目前我正在开发一个API,并且在该API中我希望已登录的用户能够喜欢/不喜欢或喜欢/不喜欢两个资源。
我的“喜欢”模型(它是Ruby on Rails 3应用程序)是多态的,属于两种不同的资源:
/api/v1/resource-a/:id/likes
和
/api/v1/resource-a/:resource_a_id/resource-b/:id/likes
问题是:我不知道如何选择尽可能使我的资源成为RESTful。我已经尝试了以下两种方法在我的URL中实现like / different结构:
案例A :(与/不同于“资源”的成员)
PUT /api/v1/resource/:id/like maps to Api::V1::ResourceController#like
PUT /api/v1/resource/:id/unlike maps to Api::V1::ResourceController#unlike
和案例B :(“喜欢”是它自己的资源)
POST /api/v1/resource/:id/likes maps to Api::V1::LikesController#create
DELETE /api/v1/resource/:id/likes maps to Api::V1::LikesController#destroy
在这两种情况下我都有一个用户会话,所以在删除/“unliking”时我不必提及相应的“like”-record的id。
我想知道你们是如何实施此类案件的!
2011年4月15日更新:“会话”是指每次请求都会发送HTTP基本身份验证标头,并提供加密的用户名:密码组合。
答案 0 :(得分:7)
我认为您在服务器上维护应用程序状态(包含用户ID的用户会话)的事实是此处的问题之一。这使得它比它需要的更加困难,并且它打破了REST的无状态约束。
在案例A 中,您已经为操作提供了URI,这也不是RESTful。 URI标识资源,并且应使用所有资源共有的统一接口来执行状态转换。我认为案例B 在这方面要好得多。
所以,考虑到这两件事,我会提出类似的建议:
PUT /api/v1/resource/:id/likes/:userid
DELETE /api/v1/resource/:id/likes/:userid
我们还有一个额外的好处,即用户只能注册一个'喜欢'(他们可以多次重复'喜欢',因为PUT
是幂等的,它具有相同的结果重要的是它执行了多少次)。 DELETE
也是幂等的,因此如果由于某种原因多次重复'不同'操作,则系统保持一致状态。当然,您可以通过这种方式实现POST
,但如果我们使用PUT
和DELETE
,我们可以看到与这些动词关联的规则似乎非常适合我们的用例。< / p>
我还可以想象另一个有用的请求:
GET /api/v1/resource/:id/likes/:userid
这将返回'Like'的详细信息,例如它的制作日期或序数(即'This is the 50th like!')。
答案 1 :(得分:2)
案例B更好,这里有一个来自GitHub API的好样本。
PUT / user / starred /:owner /:repo
DELETE / user / starred /:owner /:repo
答案 2 :(得分:0)
您实际上定义了“喜欢”资源,这是用户资源喜欢系统中其他资源的事实。因此,在REST中,您需要选择唯一标识此事实的资源名称方案。我建议(以歌曲为例):
/like/user/{user-id}/song/{song-id}
然后PUT建立了一个喜欢,DELETE删除它。 GET当然会发现有人喜欢某首歌。您可以定义GET /like/user/{user-id}
以查看特定用户喜欢的歌曲列表,并GET /like/song/{song-id}
查看喜欢特定歌曲的用户列表。
如果您认为现有会话建立了用户名,正如@joelittlejohn所指出的那样,并且不是类似资源名称的一部分,那么您违反了REST的无状态约束,并且您失去了一些非常重要的优势。例如,用户只能获得自己的喜欢,而不是他们朋友的喜欢。此外,它打破了HTTP缓存,因为一个用户的喜欢与另一个用户无法区分。