REST API的体系结构设计,包含跨资源的视图

时间:2013-10-06 12:44:28

标签: rest

寻找有关REST API架构设计的一些信息。我经常发现所需的数据是跨多个资源的视图的组合。您希望客户端将它们组合在一起,还是提供一个为客户端组合的API?

例如,假设我们正在为人们编写REST API以获得有关事件的通知。有人会以两种方式之一表示对某事件感兴趣:

  • 加入定期举办此人感兴趣的活动的组织
  • 搜索并标记由我通常不会订阅的组织运行的特定事件

我可以通过以下长步骤检索用户100的所有事件:

  1. GET /user/100/organizations返回123
  2. GET /organizations/123/events返回[15,16,20]
  3. GET /user/100/savedevents返回[35,36]
  4. GET /events/15,16,20,35,36返回所有活动
  5. 但对于客户而言,这似乎相当沉重。我几乎希望客户能够说“给我这个用​​户的所有有趣事件”:

    GET /user/100/events
    

    ...然后要求服务器了解它必须完成所有步骤1-4并返回它们,或者至少返回[15,16,20,35,36]所以它变为2步:获取事件标识;获取活动详情。

    这是否有意义,以这种方式制作一个跨多个资源的观点?

    编辑:进一步解释。我犹豫是因为我可以看到/organizations/123/events是一个干净的资源;如果与说/events?organizations=123相同,即“给我组织= 123的资源事件”。 /user/100/organizations也是如此。

    但是/user/100/events “给我组织= 123的资源事件”。它是“给我组织注册用户= 100,检索那些组织ID,然后给我组织= 123的事件,然后给我savedevents用户= 100。”

    这三个步骤本身就是一个干净的资源映射。将它们放在一起似乎很混乱。但是要求客户(尤其是Web客户端)找出所有逻辑也是如此!

2 个答案:

答案 0 :(得分:2)

我对你的问题感到有点困惑,所以我会尽量做到尽可能全面,希望我能找到你需要的答案= P.

  

我经常发现所需的数据是视图的组合   多种资源。您是否希望客户将它们组合在一起,或者   提供一个为客户端组合的API?

在真正的RESTful环境中,数据的所有横截面视图都将由服务器完成,而不是由客户端完成。

RESTful设计的主要原因是允许访问CRUD模型(创建读取更新删除< / em>)通过使用标准HTTP谓词(例如GETPOSTPUTDELETE)。将这些方法的回报存储在某种会话或cookie或其他外部方法中(例如“给我数据为bob”,“给我关于业务的数据”,“从我的前两个查询中提供数据”)超越REST方法。

您希望利用RESTful开发的方式是找到以有意义的方式组合资源的方法,以便提供方法调用一致的RESTful环境; GET读取数据,POST创建数据,PUT更新数据,DELETE删除数据)。

因此,如果您想要执行类似步骤1到步骤4的操作,我建议使用以下内容:

GET /user/{userID}/organizations --> {return all affiliated organizations}
GET /user/{userID}/events --> {return all events associated with userID}
GET /organizations/{organization}/events --> {returns all eventID's assoc. with organization}
GET /user/{userID}/savedevents -->  {return all eventID's userID saved to their profile}
GET /events/?eventID=(15,16,20,35,36) --> {return all of the events details for those eventID's}
GET /events/{eventID}--> {return events details for {eventID}}

您可能还有:

GET /events/  --> {return a complete listing of all event ID's}
GET /events/{userID}  -->  {return all events userID is associated with}
POST /event/  --> {create a new event - ID is assigned by the server}
POST /user/   --> {create a new user - ID is assigned by the server}
PUT /user/{userID}  --> {update/modify user information}

然后,如果您想要横截面的信息切片,您将获得横截面的命名资源(否则将其作为参数传递)。明确您的资源(随机FYI,仅将您的资源命名为名词 - 不是动词)。

您还问:

  

进一步解释。我的犹豫是因为我可以看到如何   / organizations / 123 / events是一个干净的资源;如果是相同的   说/ events?organizations = 123,即“给我资源事件在哪里   organizations = 123“。/ user / 100 / organizations。相同。

基本上,named resourcedresource + argument方法都可以提供相同的信息。通常,只有在需要重要描述(范围请求,日期请求,一些非常小的数据单元等)时,我才会看到RESTful设计API调用参数。如果您有一些更高阶的数据分组, CAN BE 进一步解析/反省,那么它就是一个命名资源。在你的例子中,我有两个API调用,因为RESTful规范要求通过多个路径提供数据并使用已建立的HTTP方法。但是,我也会扩展一下......

/events?organizations=123 -->  {return the eventID's associated with org=123}
/organizations/123/events  -->  {return event DETAILS for events associated with org=123}

通过Apigee

读取/读取此内容

答案 1 :(得分:0)

可能有几种方法可以解决这个问题...但是,我认为大多数情况下(如果服务由同一个提供程序管理)最好在服务器端使用逻辑并进行REST调用尽可能彼此独立(即,服务器执行所需的多个操作 - 通常从存储API资源中处理的数据的DB中读取数据)。

在这个示例中,您谈到这将意味着您的REST API将公开他感兴趣的“用户”资源和子资源“事件”(您称之为“savedevents”)。考虑到这一点,您将拥有像这样的东西:

  • POST /user/{username}/events存储用户感兴趣的新事件(或多个事件)
  • GET /user/{username}/events返回用户感兴趣的所有事件
  • GET /user/{username}/events/{eventid}返回特定活动的详细信息

要“过滤”每个组织的用户事件(以及其他过滤操作),您可以使用“查询参数”:

  • GET /user/{username}/events?organization=123

因此,服务器(或API调用)将执行您在GET /user/{username}/events中从步骤1到步骤4描述的操作。您仍然可以在API中创建其他资源(“组织”和“事件”),但是它们将在其他上下文中使用(例如存储新事件或组织等)。

HTH