繁体   English   中英

我应该在我宁静的api中加入连接词吗?

[英]should I put connecting words in my restful api or not?

假设我有一个控制器,它有三个参数:

class Dog {
    function tell (dogId, commandId, rewardId) {
         // blah
    }
}

我访问的网址可能是:

 mysite.com/dog/tell/1/2/3

在这种情况下,您必须记住参数按dogId映射到dogIdcommandIdrewardId 另一种方式可能是:

mysite.com/dog/tell/1/command/2/reward/3

或者为了更清晰(但可能更多的jiggery-pokery与您的框架):

mysite.com/tell/dog/1/command/2/reward/3

哪个更好? 哪个更常见? 乍一看似乎更清晰更好。 但是,您仍然需要记住参数的顺序,现在您还必须记住关键字。 (“它是'狗/命令/奖励'还是'命令/狗/奖励'或'狗/到/为'或......?”

思考? 参考文献? :)

您似乎没有在此处创建RESTful API。 REST API使用URI来表示资源,而不是操作( tell我看起来像是一个操作)。 资源操作由所有资源共有的接口定义。 我假设您正在使用HTTP设计REST API,因此您的公共接口由HTTP动词GET,POST,PUT,DELETE等定义。

因此,不要根据操作tell来定义我们的服务,让我们从思考资源开始:狗。 作为一个客户,让我们假设我正在寻找罗孚狗。 我与您的服务的第一次互动可能是以下请求:

GET mysite.com/dogs?q=Rover

在对此请求的响应中,我们假设我获得了一个代表Rover狗的资源的URL: mysite.com/dogs/3759

现在,让我们找出罗孚狗的状态:

GET mysite.com/dogs/3739

在回应中,我看到罗孚狗还活着,醒着站起来(即响应告诉我罗孚的状态 )。 响应还包括我可用于导致此资源状态转换的表单(即响应告诉我如何使Rover更改状态)。

现在,下一步是告诉罗孚做点什么。 我们希望罗孚的状态从站立转变为坐着(假设我们不能简单地更新流浪者状态从站立到坐着,我们只能发出一个罗孚可以选择遵循的命令 - 就像一只真正的狗!)。 让我们向Rover发布一个sit命令:

POST mysite.com/dogs/3739
<command name="sit"/>

我们可以将命令视为一种资源 - 它有一个'名称'(坐)发行者(我),一只狗(流浪者),也可以跟随或取消跟随(取决于狗的心情)。 现在,在我对此POST的回复中,我得到以下信息

Status  : 201 (Created)
Location: mysite.com/dogs/3739/commands/1299

状态告诉我Rover已收到此数据,并且已导致创建新资源(我们的命令)。 如果我们想获得此命令的状态,我们可以通过对Location头中给出的URL发出请求来查看它。 让我们这样做,找出我们新创建的命令:

GET mysite.com/dogs/3739/commands/1299

现在响应将告诉我该命令的状态。 让我们假设我们很幸运:已经遵循了命令(为此资源返回的表示包括一些信息,如followed=true )。 响应还包括一个返回资源的链接,该资源代表Rover(发出命令的狗)。

最后,当我们请求代表Rover的资源的状态时:

GET mysite.com/dogs/3739

我们从回应中看到国家转型已经发生,我们现在被告知罗孚是“坐着”。 响应还可能包括对Rover迄今为止以此URI链接形式发布的命令列表的引用:

mysite.com/dogs/3739/commands/

这是IMO更接近RESTful模型。 你在这里选择的域名可能会让我更难以解释和理解。 “命令”资源令人困惑,听起来非常冗余,但“命令”这个词实际上只是因为我们谈论的是宠物。 实际上,“命令”只是您发送给狗的消息。 当我们将“命令”一词替换为“消息”这个词时,更容易看出消息是一种肯定具有状态的资源。

所以简而言之(tl; dr):

  • 给资源提供URI,而不是操作
  • 通过发送数据创建/更新资源(导致状态转换)(不是'调用操作')
  • 如果可以,通过对客户端的每个响应,帮助他们使用链接和表单进行下一次状态转换(这些允许客户端更新自己的状态,并更新应用程序状态)。

有关更多阅读,这里描述了RESTful交互的一个很好的例子:

http://www.infoq.com/articles/webber-rest-workflow

这个咖啡店的例子在Jim Webber和Ian Robinson的书“REST in Practice”中得到了完善和扩展。

当然,重新阅读菲尔丁也是值得的(我认为第5.2节最相关):

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

很难在一篇文章中解释(对不起长度!)但我希望这会有所帮助。

就个人而言,我更喜欢拥有像mysite.com/dog/1/tell这样的网址,并通过POST传递命令= 2和奖励= 3。 狗ID可能也在数据中。 几个原因:

  1. 具有后果的操作不应该通过GET完成,但是在URL中拥有整个请求会使GET非常诱人。
  2. REST仅表示请求应包含执行操作所需的所有内容,而不是URL应该包含的内容。 考虑到#1,我甚至会说将所有内容都填充到可获取的URL中是一个坏主意。
  3. 使它更加通用; 在URL上发布HTML表单就足以测试它。
  4. 正如其他人所提到的,URL旨在形成分层命名空间。 当你把params放在URL中时,你会打破这种情况,因为(1)在'command'和'reward'之间没有明确的父/子关系,并且(2)如果没有params是可选的,它会使很多无效的网址。 命名params使它更糟糕,因为现在相同的“资源”有6个不同且功能相同的URL ......如果你的框架实际上支持这样做的话。

对于一个网站,我会说连接词是有用的,对于api,我说不是真的,好的文档是api所需要的。

mysite.com/tell/dog/1/command/2/reward/3

看起来非常像

mysite.com/tell?dog=1&command=2&reward=3

在第二种情况下,订单绝对不重要。 最有可能的是,它在第​​一种情况下也不重要。 如果我是你,我会接受任何组合,因为它显然不是层次结构,因为URL是预期的。 而且,你不能指望mysite.com/tell/dog/1做一些有用的事情。

由于狗id,命令id和奖励id只能一起使用,我也说明了这个事实,也是如此:

mysite.com/tell/dog-a-command-rewarding-by/1/2/3

甚至

mysite.com/tell/dog-a-command-rewarding-by/1-2-3

因为你不能指望mysite.com/tell/dog-a-command-rewarding-by/1做一些有用的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM