资源URL中的RESTful Querystring

时间:2017-02-24 15:42:37

标签: rest restful-architecture restful-url api-design

我正在使API更加RESTful。目前我有一个像这样的端点:

/booking?bookingid=123

我已将端点更新为更加RESTful,如下所示:

/bookings/123

预订看起来有点像这样:

{
   "bookingId":123,
   "people":[
      {
         "personId":0,
         "name":{
            "forename":"Jon",
            "surname":"Smith"
         }
      },
      {
         "personId":1,
         "name":{
            "forename":"Sarah",
            "surname":"Jones"
         }
      }
   ]
}

如果预订中包含特定姓氏,我只想退回预订,如果预订中不存在姓氏,则返回Not Found。

我希望实现这一点的方法是添加一个查询字符串:

/bookings/123?surname="Jones"

这将返回上面的预订,因为Sarah的姓氏是" Jones"预订也将返回一个查询字符串姓氏,其值为" Smith"。

我遇到的第一个问题是,如果将姓氏的属性添加到预订对象中,看起来该查询与此相反,而我遇到的另一个问题是它是'查询单个实体而不是列表,这是一个RESTful方法,如果不是那么什么是更好的方法?

3 个答案:

答案 0 :(得分:3)

社区不同意“RESTful”的定义。

与“RESTful”定义最接近的是Roy T. Fielding的Architectural Styles and the Design of Network-based Software Architectures,引入术语“REST”的论文。本论文中没有一个关于如何构建“RESTful”URL的单词。相反,我们的想法是服务器选择哪个URL方便,然后在超媒体链接中明确地将它们传达给客户端。在这种“RESTful”系统中,/booking?bookingid=123是一个非常好的网址,/_content/AcmeWebApi.dll?ENDPOINT=booking&ID=123&tc=y也是如此。

然而,在这篇论文(和“REST”这个术语)得到广泛认可之后,社区很快就从“REST”的概念转向了一系列其他的,相互矛盾的“REST是什么”的想法“,great dismay of Roy T. Fielding

因此,您的问题无法得到有效回答。

考虑“RESTfulness”是否真的是您要优化的属性,或者您是否正在使用其他属性,例如:

  • 客户端实施者易于理解
  • 与HTTP缓存等已部署组件的互操作性
  • 服务器将来可以自由更改网址
  • 就像公司X的API

并且每个都可能需要不同的URL设计。

答案 1 :(得分:1)

使用查询参数过滤掉单个资源并不常见,但它符合the spec。您可能希望自己的过滤器名称为?person-surname=,以便以后保持灵活性。您还可以考虑过滤集合(/bookings?person-surname=)并返回所有匹配的预订更有意义。

答案 2 :(得分:1)

当你通过id(即/ booking / 123 /)直接访问资源时,查询可能不是最好的选择。当你指定资源的UID [你知道肯定存在]并且期望“未找到”时,它们是不一致的。

我建议使查询更加统一,并保留在单个url参数中添加越来越多参数的规定。

/bookings?query="param1=value1 AND param2=value2"

在上面当然编码URL参数将是最佳选择,因此它将是

/bookings/123?query="param1%3Dvalue1%20AND%20param2%3Dvalue2"

这里param1可以是您的预订ID,其值为123,而param2可以是您需要的姓氏。

现在问题是param2(即姓氏)不是资源的直接属性,因此您需要考虑使用以下作为更加改进的版本。

/bookings?query="bookingId=123 AND people.surname=myname" // in your case people.name.surname

另请注意,您需要上面的param1和param2,就好像您只是传递第二个param booking.people.name.surname,有人可以预期它将返回所有带有人姓的预订值。