针对超长URI的REST最佳实践

dea*_*mon 19 rest url uri http

我有REST服务,应该通过GET接收很长的查询.比方说,我想查询具有许多地理坐标的服务,以找出有关所有这些坐标的信息.

1)我的第一个想法是使用长URI并增加 servlet容器的最大URI长度.

它看起来像这样:

GET http://some.test/myresource?query={really big JSON object}
Run Code Online (Sandbox Code Playgroud)

但是由于旧的代理服务器,似乎长度超过2 KB的URI是不可靠的(是吗?).

2)我的解决方法是首先通过POST创建临时资源,并使用此资源的URI作为实际GET请求中的参数.这看起来像这样:

POST http://some.test/temp
Request Body: {really big JSON object}

201 Created Location: http://some.test/temp/12309871

GET http://some.test/myresource?query=http://some.test/temp/12309871
Run Code Online (Sandbox Code Playgroud)

3)使用GET请求的主体.我已经阅读了问题的答案,是否使用GET请求的主体进行查询是一个好主意,并且共识是:不.甚至罗伊菲尔丁说这是一个坏主意.

4)另一种方法可以是将POST解释为"创建查询结果资源"并在请求后删除该资源.但我认为这不是RESTful而是一个坏主意.

有没有更好的方法来处理GET请求的大查询?

Ray*_*Ray 5

使用PUT

为什么?出于以下原因:

  • 仅仅因为动词PUT“可能更新”资源,并不意味着它将或必须改变资源的基础状态。
  • . 的 API 端不应创建新的资源标识符 (url) PUT。是的,从技术上讲,PUT使用客户端指定的标识符是可能的,但在这种情况下,您将访问现有资源。
  • PUT就像GET它应该是幂等的事实一样,这意味着无论您调用它的频率如何,请求的结果将始终是相同的,并且它没有副作用。

PUT意味着您将资源数据放入现有资源中。就文档/博客文章世界中的文章或帖子而言,这就像将某些文档的新修订版上传到现有资源 URL。如果您将相同的修订版上传到相同的 URL,则您返回的资源不会发生任何变化。

在您的情况下,地理数据是您正在上传的一些新资源数据,每次发出相同的请求时,您返回的结果应该是相同的。

使用GET请求动词的更纯粹的方法可能是:

  • 为查询资源类型创建端点
  • 将 JSON 查询详细信息集 POST 到查询资源端点并获取查询资源的标识符(假设它返回 的查询 id 123
  • 向 get 请求提交查询标识符http://some.test/myresource?query_id=123
  • 删除查询资源123

PUT我发现纯方法比在正文中使用查询资源数据的开销要大得多。


jld*_*ont 3

我认为 REST 的重点是处理“文档”(或类似的东西)。请求的 URI 部分用于唯一标识要处理的资源。相比之下,正文部分是文档的“内容”部分。

因此,请使用请求的“正文”部分。

另请注意,“GET”请求的语义不应该用于“PUTTING”或“POSTING”文档(与上面的“查询”示例相关的评论,该示例似乎“创建”一个对象)。

无论如何,正如您所指出的,URI 部分是有限的(我确信这是有充分理由的)。


如果您关心缓存,那么使用 ETag/Last-Modified 字段(与“条件 GET”结合使用)有助于实现此目的。

  • 这一切都在规则范围内,但是使用 GET 请求正文存在一些严重的缺点。这篇文章中解释了一些:http://stackoverflow.com/questions/978061/ (2认同)