休息标准:路径参数或请求参数

时间:2010-07-07 20:22:04

标签: rest

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

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

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

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

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

6 个答案:

答案 0 :(得分:35)

作为一般规则,路径倾向于缓存,参数往往不是。

因此...

GET /customers/bob

VS

GET /customers?name=bob

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

答案 1 :(得分:24)

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且仍包含列表(尽管为空)。仅仅因为我们要求包含不存在的项目的过滤列表并不意味着列表本身不存在。
  6. 因为它们如此不同且独立有用,您可能想要两者。客户端希望区分所有情况(例如,列表是否为空或列表本身是否存在,在这种情况下,返回/items?...的404。

    免责声明:这种做法绝不是"标准"。 me 对我来说非常有意义,尽管我感觉自己喜欢分享。

    PS:命名项目集合"得到"是一种代码气味;喜欢"项目"或类似的。

答案 2 :(得分:6)

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

有4种主要类型的请求:

 GET
 PUT
 POST
 DELETE

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

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

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

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

答案 3 :(得分:4)

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

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

答案 4 :(得分:3)

第一个版本更加清晰,允许您为排序顺序和页面等内容保留请求参数,如

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

答案 5 :(得分:1)

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

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

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