REST API可以至少以两种方式拥有参数:

作为url路径的一部分(即/api/resource/parametervalue) 作为查询参数(例如/api/resource?=参数值)

这里的最佳实践是什么?什么时候使用1,什么时候使用2,有什么一般的指导方针吗?

真实世界的例子:Twitter使用查询参数来指定间隔。(http://api.twitter.com/1/statuses/home_timeline.json?since_id=12345&max_id=54321)

把这些参数放在URL路径中会被认为是更好的设计吗?


当前回答

There are no hard and fast rules, but the rule of thumb from a purely conceptual standpoint that I like to use can briefly be summed up like this: a URI path (by definition) represents a resource and query parameters are essentially modifiers on that resource. So far that likely doesn't help... With a REST API you have the major methods of acting upon a single resource using GET, PUT, and DELETE . Therefore whether something should be represented in the path or as a parameter can be reduced to whether those methods make sense for the representation in question. Would you reasonably PUT something at that path and would it be semantically sound to do so? You could of course PUT something just about anywhere and bend the back-end to handle it, but you should be PUTing what amounts to a representation of the actual resource and not some needlessly contextualized version of it. For collections the same can be done with POST. If you wanted to add to a particular collection what would be a URL that makes sense to POST to.

这仍然留下了一些灰色区域,因为一些路径可以指向多少子代的父资源,这在某种程度上是自由裁量的,取决于他们的使用。这所画出的一条界限是,任何类型的传递表示都应该使用查询参数来完成,因为它不会有底层资源。

为了响应原始问题中给出的真实示例(Twitter的API),参数表示一个可传递查询,它过滤资源的状态(而不是层次结构)。在那个特定的例子中,向由这些约束表示的集合中添加数据是完全不合理的,而且该查询将无法表示为在对象图中有任何意义的路径。

The adoption of this type of resource oriented perspective can easily map directly to the object graph of your domain model and drive the logic of your API to the point where everything works very cleanly and in a fairly self-documenting way once it snaps into clarity. The concept can also be made clearer by stepping away from systems that use traditional URL routing mapped on to a normally ill-fitting data model (i.e. an RDBMS). Apache Sling would certainly be a good place to start. The concept of object traversal dispatch in a system like Zope also provides a clearer analog.

其他回答

根据REST实现,

1)路径变量用于对资源的直接操作,如联系人或歌曲 前女友. . 获取etc /api/resource/{songid}或 GET etc /api/resource/{contactid}将返回相应的数据。

2)查询perms/参数用于间接资源,如一首歌的元数据 . ., GET / api /资源/ {songid} ?Metadata =genre它将返回特定歌曲的类型数据。

这取决于设计。HTTP上的REST没有uri规则(主要是它们是唯一的)。通常这涉及到品味和直觉的问题……

我采取以下方法:

url path-element:资源和它的path-element组成了一个目录遍历和一个子资源(例如/items/{id}, /users/items)。不确定的时候问问你的同事,如果他们认为遍历和他们认为在“另一个目录”最有可能的路径元素是正确的选择 Url参数:当没有遍历时(有多个查询参数的搜索资源就是一个很好的例子)

这个主题的一个“维度”被忽略了,但它非常重要:有时“最佳实践”必须与我们正在实现或增强REST功能的平台相一致。

实际的例子:

现在许多web应用程序都实现了MVC(模型、视图、控制器)架构。他们假设提供了一个特定的标准路径,当那些web应用程序带有“启用SEO url”选项时更是如此。

这里只提一个相当有名的网络应用程序:OpenCart电子商务商店。 当管理员启用“SEO url”,它期望说url来一个相当标准的MVC格式,如:

http://www.domain.tld/special-offers/list-all?limit=25

在哪里

special-offers是处理URL的MVC控制器(显示special-offers页面) List-all是控制器要调用的动作或函数名。(*) Limit =25是一个选项,表示每页将显示25个项目。

(*) list-all是我使用的一个虚构的函数名。实际上,OpenCart和大多数MVC框架都有一个默认的、隐含的(通常在URL中省略)索引函数,当用户想要执行默认操作时,就会调用该索引函数。真实世界的URL是:

http://www.domain.tld/special-offers?limit=25

现在有了一个类似于上面的相当标准的应用程序或框架结构,你经常会得到一个针对它进行优化的web服务器,为它重写URL(真正的“非SEOed URL”应该是:http://www.domain.tld/index.php?route=special-offers/list-all&limit=25)。

因此,作为开发人员,你要面对的是处理现有的基础设施,并适应你的“最佳实践”,除非你是系统管理员,确切地知道如何调整Apache / NGinx重写配置(后者可能很讨厌!)等等。

因此,你的REST API通常会更好地遵循参考web应用程序的标准,无论是一致性还是易用性/速度(从而节省预算)。

回到上面的实际例子,一个一致的REST API应该是类似这样的url:

http://www.domain.tld/api/special-offers-list?from=15&limit=25

或者(非SEO URLs)

http://www.domain.tld/index.php?route=api/special-offers-list?from=15&limit=25

使用“路径形成”参数和“查询形成”参数的混合。

作为一名经常在客户端工作的程序员,我更喜欢使用查询参数。另外,对我来说,它将URL路径从参数中分离出来,增加了清晰度,并提供了更多的可扩展性。它还允许我在URL/URI构建和参数构建器之间有单独的逻辑。

我很喜欢曼努埃尔·阿尔达纳说的另一种选择如果有某种树的话。我可以看到用户特定的部分被树形分开。

如果有记录在案的最佳实践,我还没有找到它们。然而,当我决定在url中放置参数时,这里有一些指导原则:

可选参数往往更容易放在查询字符串中。

如果您希望在参数值与现有资源不对应时返回404错误,那么我倾向于使用路径段参数。例如:/customer/232,其中232不是有效的客户id。

然而,如果你想返回一个空列表,那么当参数没有找到时,我建议使用查询字符串参数。例如/联系人吗?name =戴夫

如果一个参数影响URI空间的整个子树,则使用路径段。例如,语言参数/en/document/foo.txt和/document/foo.txt?语言= en

我希望唯一标识符位于路径段中,而不是查询参数中。

uri的官方规则可以在这个RFC规范中找到。这里还有另一个非常有用的RFC规范,它定义了参数化uri的规则。