【问题标题】:Does this break the statelessness of a RESTful API?这会破坏 RESTful API 的无状态性吗?
【发布时间】:2016-07-28 18:39:05
【问题描述】:

采用这种 API 设计:

  • /articles/{id} - 返回一篇文章。客户端在标头中提供一个令牌来识别它们。
  • /updated-articles - 返回自客户端上次调用此端点以来已更新的文章集合,并且仅包括此客户端先前请求的文章。客户端在标头中提供一个令牌来识别它们。

第二个 enpoint 不太适合我。第二个 enpoint 的设计动机是 客户端不需要跟踪他们最后一次请求的时间。这是否打破了 RESTful API 的“无状态”约束?另一种方法是/updated-articles?since=YYYY-MM-DD,但这需要客户记住

【问题讨论】:

  • 为什么不改用/articles?updated_since=YYY-MM-DD
  • 作为一个结构,看起来确实不错。 “为什么不”的原因是客户需要跟踪他们对YYYY-MM-DD 的价值,这违反了要求。
  • 您的客户不必是无国籍的。只有您的服务器应用程序。
  • 明白。然而,实际上我收到的业务需求不允许我根据 RESTful 原则设计 API。我被要求在服务器上保持状态。我想这只是一个严重的不匹配。
  • 老实说,给你这个要求的人只是让事情变得比他们必须的更难。你问为什么?

标签: rest restful-architecture


【解决方案1】:

您的“令牌”基本上是一个客户端 ID,记住他们上次访问日期的事实是在服务器上保持客户端状态。

想一想:如果您必须扩展您的服务,您是否可以简单地插入一个新服务器,复制您的服务文件,并通过循环算法在两个服务器中的一个或另一个上重定向(无需他们分享信息)?显然不,因为您需要在两台服务器之间共享您的表tokens<->date of last consultation。所以不,它绝对不是无国籍的。

另外,我不明白你的意思:

另一种方法是 /updated-articles?since=YYYY-MM-DD 但这需要客户记住

令牌不需要客户记住吗?相反,这种方式将是 RESTful,因为客户端状态(上次咨询的日期)将保存在客户端。

【讨论】:

  • 虽然我同意你的大部分评论,但我想引用 wikipedia 关于无状态的话题:... The session state can be transferred by the server to another service such as a database to maintain a persistent state for a period and allow authentication. 数据库连接通常在多个服务器之间共享,因此使服务器能够转移DB-Layer 的当前状态,因此处理后续请求的进一步服务器应该能够访问该状态。
  • “令牌不需要客户记住吗?”。我不确定我是否跟随。该令牌随着时间的推移具有静态值,它是一个访问令牌。客户端需要记住YYYY-MM-DD 的值。传递给我的业务要求是“客户不应该需要跟踪他们的最后通话日期”。
【解决方案2】:

基本上,不,我认为您的第二个资源不会打破无国籍状态。

我认为让您的客户跟踪他们自己的“更新时间”时间戳是可以的。你的 api 应该是无状态的。客户端不必是无状态的。

如果有的话,客户端应该保留很多状态。客户端将成为一个用户及其特定需求的中心设备。它负责跟踪用户的需求和当前状态。在这种情况下,必须有人存储该时间戳。我认为应该是您的客户端,而不是您的服务器。

这只是我的意见。

我确实找到了一篇关于无国籍真正含义的文章,我认为它也可以使您受益here

【讨论】:

    【解决方案3】:

    我们应该避免创建没有相关实体的端点。因此,而不是/updated-articles?since=<timestamp>,更好的方法应该是:

    • /articles?updated=true&since-last-request=true
    • /articles?updated-since-last-request=true

    如果预期结果应该影响所有客户端。这意味着每个请求时间戳都必须保存在服务器上。或者

    • /articles?updated-since=<timestamp>

    如果预期结果取决于每个客户端的行为。这似乎是你的情况。

    前者或后者(或两者)之间的选择取决于用例。但主要的一点是避免创建没有相关实体的端点并且有由参数定义的特殊情况。

    作为指导:

    端点是实体形容词是参数,动词是HTTP请求方法

    这也意味着一个简单的“GET /articles”意味着返回所有篇文章。为避免滥用,您可以根据具体情况发出适当的 4xx 代码。

    【讨论】:

    • 我看到你说的似乎有道理,但你能否进一步解释一下/updated-articles 是如何“没有相关实体”的?
    • @edev 我的意思是 articles 是实体,但 updated文章 不是,它们只是前者的子集。在我的设计中,我避免创建像端点(实体)这样的子集,而是更喜欢使用参数来定义它们。
    猜你喜欢
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多