在REST中,如何在分页资源时处理对findAll操作的GET请求?

时间:2012-02-09 14:43:18

标签: rest uri restful-architecture hateoas

在RESTful服务中,不能一次检索的资源都是分页的。例如:

获取/foo?page=1

问题是,我该如何处理getAll请求,例如:
获取/foo

考虑到可发现性/ HATEOAS,我看到了一些选择:

  1. 返回 405 Method Not Allowed 并在第一页中包含一个Link标头: Link=<http://localhost:8080/rest/foo?page=0>; rel=”first“
  2. 返回 400错误请求并包含链接标头(与上述相同)
  3. 303 See Other 返回到第一个分页页
  4. 返回 200 OK ,但实际上只返回第一页(并将下一页的URI包含在链接中): Link=<http://localhost:8080/rest/foo?page=1>; rel=”next“
    • 注意:我宁愿不这样做,如果他们没有明确要求,我不会默认管理客户端的任何内容。
  5. 这些当然只有几个选择。我倾向于第一个,但我不确定是否有一个我不知道的最佳实践。 任何反馈都表示赞赏。 谢谢。

3 个答案:

答案 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的用户明确设置startcount

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.zipGET /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;

因此它们之间存在细微差别。因此,您可以将问题分解为规范问题:有多个网址指向同一资源(/foofoo?page=1,但您有首选版本的网址(foo?page=1)。所以现在有一些RESTful方法的选项:

  • 如果查询中没有给出page - 参数,请在处理时使用默认值(例如1)。我认为在这种特定情况下,即使你指出它是不好的做法,也可以使用默认值。
  • 回复303 See Other,在位置 -header中提供首选网址(如上所述)。我认为 3xx -response是处理重复/规范内容的最佳方式(也是最有可能的REST)。
  • 如果您想强制客户端提供page参数(如zzzzBov在其答案中所述),请回复400 Bad Request。请注意,此响应没有类似 Location 标头(如您的问题中所假设的),因此解释了请求失败的原因和/或正确的URL(如果给出的话) )必须转到响应的实体主体。另请注意,根据规范,当客户端提交错误/格式不正确的表示(!不是URL!)以及PUTPOST请求时,通常会使用此响应。所以请记住,这对客户来说也可能有点模棱两可。

就我个人而言,我认为您回复 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。

这是一个背景问题。