具有经过身份验证的用户的REST API的无状态

时间:2012-07-18 09:02:59

标签: api http rest hateoas

我正在设计一个REST Http api。 (使用HATEOAS的东西,让客户“更简单”,并避免客户做复杂的事情,而不是让api告诉他们该怎么做......)

由于应用程序的社交特性,为了与应用程序进行交互,用户需要进行身份验证,并且每个用户都会对数据略有不同的“视图”。 我们以twitter为例,对每个人来说都会更容易。

要对用户进行身份验证,我们将轻松使用OAuth。

因此,在客户端(ios app ...)中,随机用户可能会看到用户列表应该看到:

Adrien: Following
John:   Not Following
Rambo:  Not Following

另一位用户可能会看到:

Adrien: Following
John:   Not Following
Rambo:  Following

要实现这一点,第一个解决方案将是客户端(在oauth术语中,iphone / web / etc应用程序),以获取经过身份验证的用户遵循的所有用户的列表,以及每次客户端显示列表时,将每个用户与被跟踪用户列表进行比较,以确定其是否应显示“未关注”或“关注”。

请求/回复将是:

GET /users
Authorization: OAuth token...

[
  {"id": 1, "name": "Adrien"},
  {"id": 2, "name": "John"},
  {"id": 3, "name": "Rambo"}
]

GET /users/{myid}/following
Authorization: OAuth token...

[1, 3, 25, 1210, 9]

这似乎是相当无国籍的。好。

现在如果我想让客户端开发人员生活更轻松,并直接嵌入用户列表响应,每个用户与相关身份验证用户之间的关系,该怎么办:

GET /users
Authorization: OAuth token...

[
  {"id": 1, "name": "Adrien", "relationship": "Following"},
  {"id": 2, "name": "John", "relationship": "Not Following"},
  {"id": 3, "name": "Rambo", "relationship": "Following"}
]

所以,问题:

  • 它似乎打破了“无国籍”的事情,是否真的打破了 REST 无状态约束?
  • 接下来,你认为api这样做是好还是坏?

5 个答案:

答案 0 :(得分:15)

您绝对应该在用户列表响应中嵌入关系。迫使客户计算它是不好的做法。

这不会破坏REST的无状态约束,因为它是无状态的交互,而不是系统。服务器几乎总是要存储和维护状态。例如,服务器需要维护谁在跟踪谁的状态。

最后,我认为你并没有完全获得超媒体作为应用引擎状态的“状态”部分。基本上,资源是状态机。当您GET资源时,呈现的有效状态转换在响应中具有超媒体控件(链接和表单)。通过以下链接并提交表单,客户可以更改这些资源的状态。

答案 1 :(得分:13)

在响应正文中包含关系类型的描述并不会破坏无状态约束。无状态约束意味着Web服务器可以响应请求,而不依赖于任何先前的请求(如TomJacobkgb所述)。

我没有资格说出你所做的是否是“最佳做法”,但总的来说,罗伊给出了以下理由支持和反对使你的API无状态(参见他的{{{5.1.3节) 3}})。像生活中的许多事情一样,需要权衡:

无状态系统的问题

  • 请求可能需要更大。由于数据未在请求之间存储在服务器上,因此每个请求可能需要反复包含相同的内容。

  • 在无状态系统中,服务器依赖于客户端正确维护状态。

无国籍系统的好处

  • 您知道请求仅根据其内容尝试实现的目标。

  • 可靠性,因为它“简化了从部分故障中恢复的任务”。有关详细信息,请参阅dissertation中引用的reference 133

  • 改进了可扩展性。在请求之间管理状态,特别是在分布式环境中,可能非常复杂。这里首先想到的是Roys dissertation,对于单个服务器,单个流程实例来说很好,但它不能很好地扩展。

RESTful资源

另外,根据Roy对资源的定义,我会考虑如何定义您的资源,每个用户都会得到稍微不同的数据“视图”。 Roy将资源定义为随时间变化的成员函数(参见ASP.NET InProc session state中的5.2.1.1节)。您在上面定义的用户列表资源因时间和授权标头而异。同时请求/用户的两个不同客户端很可能最终得到完全不同的结果。 这会使缓存结果变得更加困难。

编辑:使用HTTP vary标头可以缓存它。

答案 2 :(得分:4)

如果您认为向打破无状态约束的用户添加“关系”属性,那么当请求中包含“/ following”时添加它也会破坏它。

我会说“无国籍”意味着没有回应取决于其他请求/回复。

HTTP是stateless协议,但它可以在请求/响应头中存储大量有关用户的数据(我不是在讨论会话/ cookie)

答案 3 :(得分:3)

来自Roy Fieldings 建筑风格和 基于网络的软件架构设计

3.4.3 Client-Stateless-Server (CSS)

The client-stateless-server style derives from client-server with the additional
constraint that no session state is allowed on the server component. 
Each request from client to server must contain all of the information necessary 
to understand the request, and cannot take advantage of any stored context on 
the server. Session state is kept entirely on the client.

链接:http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

因此,您直接在响应中嵌入实体数据不会使您的解决方案成为非无状态的。

良好做法:

实际提供用户数据要比客户端的数字列表更好,以确定如何处理。

但是,根据每个用户的数据量,您可以考虑提供指向用户资源的链接列表,并说明“跟随”关系。然后,客户端可以获取所需用户的详细信息。您选择哪种解决方案取决于您认为客户需要什么,最终可能会采用多种方法。

答案 4 :(得分:1)

我没有看到将“关系”信息嵌入/users资源和无状态约束之间的相关性。所以我认为没有问题。

但是,我认为你正在打破“资源识别”的限制。

/Users对你而言/Users对我来说将显示一组完全不同的关系。我认为这些是两种不同的资源,因此应该有不同的URI。

在某些情况下,您可以根据用户的身份更改表示(例如出于安全原因),但这种情况对我的喜好来说太多了。