在RESTful服务中,不能一次检索的资源都是分页的。例如:
获取/foo?page=1
问题是,我该如何处理getAll请求,例如:
获取/foo
考虑到可发现性/ HATEOAS,我看到了一些选择:
Link=<http://localhost:8080/rest/foo?page=0>; rel=”first“
Link=<http://localhost:8080/rest/foo?page=1>; rel=”next“
这些当然只有几个选择。我倾向于第一个,但我不确定是否有一个我不知道的最佳实践。 任何反馈都表示赞赏。 谢谢。
答案 0 :(得分:2)
让我们从REST不是像SOAP这样的固定协议这一事实开始,它只是构建服务的一种方式,类似于语言被描述为面向对象的方式。
尽管如此,我建议按照以下方式处理:
将RESTful调用视为函数声明。
GET /foo
foo()
某些功能需要参数。
GET /foo?start=??&count=??
foo(start, count)
有些语言支持默认参数,有些则不支持;你可以自己决定如何处理参数。
使用默认参数,您可以假定该函数已定义为
foo(start = 0, count = 10)
因此,对GET /foo
的调用实际上等同于GET /foo?start=0&count=10
,而对GET /foo?start=100
的调用则相当于GET /foo?start=100&count=10
。
如果不想要默认参数,您可以强制API的用户明确设置start
和count
:
foo(start, count)
以便拨打GET /foo
会返回400 Bad Request
状态代码,但是对GET /foo?start=0&count=10
的调用会返回200 OK
状态代码以及指定范围。
在任何一种情况下,您都必须决定如何处理错误,例如
GET /foo?start=-10&count=99999999
如果参数有最大值和最小值,则需要决定是否规范化参数,或者只返回错误。上一个示例可能会返回400 Bad Request
状态代码,但也可能会被限制为:
GET /foo?start=0&count=1000
最后,由您自行决定在您的申请环境中最有意义的内容。
答案 1 :(得分:2)
从RESTful的角度来看,我认为同样处理两种表示形式完全没问题。考虑一个您想要下载多个版本的软件,最新的版本是3.8。因此,如果您想获得最新版本,可以使用GET /software/version/latest.zip
和GET /software/version/3.8.zip
解决此问题,直到出现更新版本为止。所以两个不同的链接指向同一个资源。
我喜欢想象分页几乎一样。在第一页上总是有最新的文章。因此,如果未提供page
- 参数,则可能只是暗示其为1。
rel
属性的方法方向略有不同。它是Google的一个创造,可以更好地处理重复内容的问题,主要用于区分主要内容和#34;页面和分页页面。以下是如何使用它:
//first page:
<link rel="next" href="http://www.foo.com/foo?page=2" />
//second page:
<link rel="prev" href="http://www.foo.com/foo?page=1" />
<link rel="next" href="http://www.foo.com/foo?page=3" />
//third and last page:
<link rel="prev" href="http://www.foo.com/foo?page=2" />
因此,从SEO的角度来看,使用这些元素是一个好主意(并由Google推荐)。他们也完美地遵循REST的资源导向理念和资源的超媒体表示。
选择您的一条建议,我认为303 See Other
是正确的方法。它旨在用于此类目的,并且是规范化资源的好方法。你可以通过许多URI使它们可用,但是有一个真实的&#34;表示的URI(如具有不同版本的软件)。
根据规范,响应应如下所示:
303 See Other
Location: http:www.foo.com/foo?page=1
<a href="http:www.foo.com/foo?page=1">http:www.foo.com/foo?page=1</a>
所以你提供了一个带有&#34;真实&#34;的位置标题。表示,并且正文应包含链接到新URI的超文本文档。请注意,根据规范,客户端期望将GET请求发送到Location的值,但它不会必须。
//编辑作为您评论的答案(是的,在没有证明的情况下声称可以采取行动是非常糟糕的做法:-) - 我的不好!):
Google于2011年9月在Official Webmaster Central Blog上展示了rel="next"
和rel="prev"
属性。它们可以另外用于(或在某些情况下代替)rel="canonical"
tag。
在这些链接下,您可以找到它们之间的差异解释:
rel="next"
和rel="prev"
link elements是&#34;表示分页系列中组件网址之间的关系&#34; rel="canonical"
&#34;允许您公开指定首选的网址版本&#34; 因此它们之间存在细微差别。因此,您可以将问题分解为规范问题:有多个网址指向同一资源(/foo
和foo?page=1
,但您有首选版本的网址(foo?page=1
)。所以现在有一些RESTful方法的选项:
page
- 参数,请在处理时使用默认值(例如1)。我认为在这种特定情况下,即使你指出它是不好的做法,也可以使用默认值。page
参数(如zzzzBov在其答案中所述),请回复400 Bad Request。请注意,此响应没有类似 Location 标头(如您的问题中所假设的),因此解释了请求失败的原因和/或正确的URL(如果给出的话) )必须转到响应的实体主体。另请注意,根据规范,当客户端提交错误/格式不正确的表示(!不是URL!)以及PUT
或POST
请求时,通常会使用此响应。所以请记住,这对客户来说也可能有点模棱两可。就我个人而言,我认为您回复 405 Method Not Allowed 的建议是个好主意。根据规范,您必须提供允许 - 标题列出允许的方法。但是这个资源可以采用哪些方法?我只能想到POST
。但是,如果您不希望客户端POST
,也可以使用 403 Forbidden 回复,并解释为何被禁止,或者 {{3如果您不想告诉它为什么被禁止,那么。所以它可能有点含糊不清(在我看来)。
使用link
- 提及rel
- 元素的元素,如你在问题中提出的那样,并非基本上是“RESTful”。因为它只是在资源表示中定居的超媒体。但是你的问题(据我所知)是你想要决定如何回应特定的请求和服务的表示。但它仍然没有绝对的意义:
您可以将整个SEO问题视为使用rel="next/prev/canonical"
的副作用,但请记住,他们还会创建连接性(作为具有链接的质量),这是其中之一REST的特征(见404 Not Found)。
如果您想深入了解RESTful Web服务(完全值得),我建议您阅读Leonard Richardson和Sam Ruby的书Roy Fielding's dissertation。
答案 2 :(得分:0)
在某些情况下,不隐式管理客户端的任何内容可能会导致覆盖复杂的界面,例如,消费者不是技术人员或不打算在界面之上构建,例如在网页中。在这种情况下,甚至200也可能是合适的。
在其他情况下,我同意隐式管理将是一个坏主意,因为消费者希望能够正确预测响应以及可能需要简单规范的地方。在这种情况下405,400和303。
这是一个背景问题。