HasMany RESTful(或反RESTful)设计?

时间:2013-10-01 18:21:15

标签: rest url architecture

所以我一直在阅读很多有关RESTfull设计的内容 - 特别是处理资源。

采用用户帖子评论的典型示例,关系为:

  

用户---(hasMany)--->帖子---(hasMany)--->评论

最初可能会考虑公开类似的内容:

GET /users               GET /posts               GET /comments 
POST /users              POST /posts              POST /comments 
GET /users/id            GET /posts/id            GET /comments/id
PUT /users/id            PUT /posts/id            PUT /comments/id
DELETE /users/id         DELETE /posts/id         DELETE /comments/id

但是,然后,说我想要特定用户制作的某个帖子的所有评论。我需要做类似的事情:

GET /users/id
   > someUser
   > var postIds = someUser.posts()
GET /posts?id=<postIds[0]>&id=<postIds[1]>&...
   > somePosts
   >  **application user inspects posts to see which one they care about**
   > var postOfInterest = somePosts[x]; 
   > var postId = postOfInterest.id;
GET /comments?id=postId
   > someComments (finally)

假设我只关心其所有者的上下文中的帖子评论。假设一个不同的资源结构可能(或可能不是)更自然:

GET /users
POST /users  
GET /users/id   
PUT /users/id
DELETE /users/id

GET /users/id/posts
POST /users/id/posts
GET /users/id/posts/id
PUT /users/id/posts/id
DELETE /users/id/posts/id

GET /users/id/posts/id/comments
POST /users/id/posts/id/comments
GET /users/id/posts/id/comments/id
GET /users/id/posts/id/comments/id
GET /users/id/posts/id/comments/id

对我来说,这可能更好地代表了资源。然后我需要的是:

GET /users/id/posts
   > somePosts
   > **application user inspects posts to see which one they care about**
   > var postOfInterest = somePosts[x];
   > var postId = postOfInterest.id;
GET /users/id/posts/postId/comments
   > someComments

这似乎更像是导航文件系统而不是之前的方法 - 但我不知道它的RESTfull是否完全(也许这就是REST试图摆脱的原因),因为在为了访问评论资源,我需要知道它属于哪个用户发布。但前者需要3个请求,而后者只需2个。

思想?

2 个答案:

答案 0 :(得分:1)

很多好的REST是意见,但我会说你的第二种方法通常更“RESTful”。

基本上,您确实需要REST API和文件系统中的层次结构,例如导航而不是查询参数。如果您像API一样关注HATEOS,因为有人可以浏览您的API。

答案 1 :(得分:1)

在您的第二个示例中, GET /users/idGET /users/id/posts非常重要,这样当用户信息的请求发出时,它不会包含所有帖子(或者他们的ID)。第二个请求也将返回他们的帖子。用户通常在论坛中拥有数千个帖子。

缺点是api用户总是必须知道它想要获得评论的帖子的作者。他基本上会向你的服务器发一个“给我那个用户并给我他/她的帖子”的请求,这意味着你的服务器将对该用户进行查询,然后选择他的帖子。相反,对于您的用户和服务器来说,单独请求更加方便 - “给我那个用户”,“给我那个帖子”和“给我那个评论”。这意味着您必须单独存储用户,帖子和评论,并为每个帖子/评论存储其作者的ID,以便您可以选择作者的帖子/评论(“给我这个用​​户的帖子”,或者只是“给我这个帖子”)

我个人会使用这种请求变体

GET user
GET post
GET comment
...

对于每个请求,我都会实现一个where子句,它将为我的api用户提供更多选项来进行特定选择。例如GET posts where userId='myID'。它可以使用http://myapi.mydomain.com/post?userId=user1 where或标题内部实现。它将返回该用户的帖子列表。您还可以为帖子的ID http://myapi.mydomain.com/post?id=123添加post?id=id子句,该子句仅返回此帖子。请注意,对于第一种情况 - 当您获取帖子列表时 - 您只能返回帖子的某种简短信息(例如ID,作者,摘要...)并要求{{1}}的其他请求完整的帖子内容。

实施此实施将至少为您带来两个好处:

  • api的用户只需要知道一个id来获取一些信息 - postID获取帖子的内容/评论,userId获取该用户的所有帖子/评论
  • 选择在服务器上完成,因此通过网络传输的数据更少,这意味着更快的响应(如果最终用户使用移动计划或其他内容,可能会降低成本)

在我看来,这个实现为您提供了松散耦合的对象(用户,帖子,评论)和更灵活的查询