【问题标题】:Rest Standard: Path parameters or Request parameters休息标准:路径参数或请求参数
【发布时间】:2011-03-13 00:38:37
【问题描述】:

我正在创建一个新的 REST 服务。

将参数传递给 REST 服务的标准是什么。从 Java 中的不同 REST 实现中,您可以将参数配置为路径的一部分或请求参数。例如,

路径参数 http://www.rest.services.com/item/b

请求参数 http://www.rest.services.com/get?item=b

有谁知道每种传递参数方法的优点/缺点。似乎将参数作为路径的一部分传递似乎更符合 REST 协议的概念。也就是说,单个位置表示唯一的响应,对吗?

【问题讨论】:

标签: rest


【解决方案1】:

一般来说,路径往往会被缓存,而参数往往不会被缓存。

所以...

GET /customers/bob

GET /customers?name=bob

第一个更可能被缓存(假设正确的标头等),而后者可能不被缓存。

【讨论】:

【解决方案2】:

第一个变体更简洁一些,允许您为排序顺序和页面等内容保留请求参数,如

http://www.rest.services.com/items/b?sort=ascending;page=6

【讨论】:

    【解决方案3】:

    “请求参数”的第二个示例不正确,因为“get”包含在路径中。 GET 是请求类型,它不应该是路径的一部分。

    有 4 种主要类型的请求:

    得到 放 邮政 删除

    GET 请求应该始终能够在请求正文中没有任何信息的情况下完成。此外,GET 请求应该是“安全的”,这意味着请求不会修改任何重要数据。

    除了上面提到的缓存问题之外,URL 路径中的参数往往是必需的和/或预期的,因为它们也是您的路由的一部分,而在查询字符串中传递的参数更易变,不会影响哪一部分您的应用程序的请求被路由到。虽然也可能通过 url 传递一组可变长度的参数:

    GET somedomain.com/states/Virginia,California,Mississippi/
    

    "Restful Web Services" 是本主题入门读物的好书。虽然我会警告你准备略过一些多余的信息。

    【讨论】:

    • get 不是指 http 方法,而是指服务的操作。
    【解决方案4】:

    我认为这取决于。一个资源的一个 URL。如果您想以稍微不同的方式接收该资源,请给它一个查询字符串。但是对于可以提供不同资源的值,请将其放在路径中。

    因此,在您的示例中,变量的值与返回的资源直接相关。所以它在路径中更有意义。

    【讨论】:

      【解决方案5】:

      这是一个很好的基本问题。我最近得出的结论是远离使用路径参数。它们导致不明确的资源解析。 URL 基本上是在服务器某处运行的一段代码的“方法名称”。我不喜欢将变量名与方法名混用。您的方法的名称显然是“客户”(恕我直言,这是一种方法的烂名称,但 REST 人喜欢这种模式)。您传递给此方法的参数是客户的姓名。查询参数适用于此,如果需要,甚至可以缓存此资源和查询参数值。

      没有物理 IT 客户资源。以客户命名的客户文件夹下的磁盘上可能没有文件。这是一个执行某种数据库事务的 Web 服务。 “资源”是您的服务,而不是客户。

      对 REST 和网络动词的痴迷让我想起了面向对象编程的早期阶段,我们试图将代码塞进物理对象的虚拟表示中。然后我们意识到对象通常是系统中的虚拟概念。当以正确的方式完成时,OO 仍然很有用。如果您意识到 RESTful 资源是服务而不是对象,那么 REST 也很有用。

      【讨论】:

      • 我认为这有点偏离目标,并推动了对古老 RPC 风格界面的讨论。在面向资源的世界中​​,您的 URL 不是方法名称;它是资源的位置。您的“客户”绝对不是一种方法,而是该资源的名称。您的“方法”是服务墙后面的实现细节。您通过 HTTP 的语义通过理解这些语义的服务与资源进行交互。这些是您正在寻找的基础知识。
      【解决方案6】:

      tl;dr:你可能想要两者。


      项目 #42 存在:

      GET /items/42
      Accept: application/vnd.foo.item+json
      --> 200 OK
      {
          "id": 42,
          "bar": "baz"
      }
      
      GET /items?id=42
      Accept: application/vnd.foo.item-list+json
      --> 200 OK
      [
          {
              "id": 42,
              "bar": "baz"
          }
      ]
      

      第 99 项不存在:

      GET /items/99
      Accept: application/vnd.foo.item+json
      --> 404 Not Found
      
      GET /items?id=99
      Accept: application/vnd.foo.item-list+json
      --> 200 OK
      [
      ]
      

      说明和方法

      1. /items/{id} 返回 item,而 /items?id={id} 返回 item-list
      2. 即使过滤后的item-list 中只有一个元素,仍会返回单个元素的列表以保持一致性(而不是元素本身)。
      3. 恰巧id 是一个独特的属性。如果我们要过滤其他属性,这仍然会以完全相同的方式工作。
      4. 集合资源的元素只能使用唯一属性(例如,作为集合的子资源的键)来命名,原因很明显(它们是普通资源,URI 唯一标识资源)。
      5. 如果在使用过滤器时未找到该元素,则响应仍为OK,并且仍包含一个列表(尽管为空)。仅仅因为我们请求一个包含不存在项目的过滤列表并不意味着该列表本身不存在。

      因为它们是如此不同且独立有用,所以您可能需要两者。客户希望区分所有情况(例如,列表是否为空或列表本身不存在,在这种情况下,您应该/items?...返回 404)。

      免责声明:这种方法绝不是“标准的”。这对来说很有意义,尽管我想分享。

      PS:将项目集合命名为“get”是一种代码味道;更喜欢“项目”或类似的东西。

      【讨论】:

      • 很好的答案,详细阐述了资源位置和资源服务之间的关键区别。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-22
      相关资源
      最近更新 更多