超长 URI 的 REST 最佳实践

发布于 2024-08-17 14:18:18 字数 1064 浏览 2 评论 0原文

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

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

它看起来像这样:

GET http://some.test/myresource?query={really big JSON object}

但由于旧的代理服务器,超过 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

3) 使用 GET 请求的正文。我已经阅读了以下问题的答案:使用 GET 请求的正文进行查询是否是一个好主意,共识是:否。甚至 Roy Fielding 也表示这是一个坏主意

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

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

I have REST services which should receive really long queries via GET. Say for example I want to query a service with many geographical coordinates to find out something about all this coordinates.

1) My first thought was to use long URIs and increase the max URI length of the servlet container.

It would look like this:

GET http://some.test/myresource?query={really big JSON object}

But it seems that URIs longer than 2 KB are not reliable due to old proxy servers (is that right?).

2) My workaround is to create a temporary resource via POST first and use the URI of this resource as parameter in the actual GET request. That would look like this:

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

3) Use body of GET request. I've read the answers to the question whether it is a good idea to use the body of a GET request for the query, and the consensus is: no. Even Roy Fielding says that this is a bad idea.

4) Another approach could be to interpret POST as "create query result resource" and delete this resource after the request. But I consider that to be not RESTful and to be a bad idea.

Is there a better way to handle big queries with GET requests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

黎夕旧梦 2024-08-24 14:18:18

使用PUT

为什么?原因如下:

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

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

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

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

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

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

Use PUT.

Why? For the following reasons:

  • Just because the verb PUT 'may update' the resource, doesn't mean it will or must alter underlying state of the resource.
  • No new resource identifier (url) should be created by the API side of a PUT. Yes, technically a PUT with a client specified identifier is possible, but in this case you're hitting an existing resource.
  • PUT is like GET in the fact that it should be idempotent, meaning the results of the request will always be the same regardless of how often you call it and it has no side effects.

PUT means you're putting resource data to an existing resource. In terms of a article or post in the document / blog post worlds, it would be like uploading a new revision of some document to an existing resource URL. If you upload the same revision to the same URL, nothing should change in the resource you get back.

In your case, the geo data is some new resource data you're uploading and the result you get back should be the same every time you make the same request.

A more purist method to use the GET verb for the request might be:

  • Create an endpoint for a query resource type
  • POST the JSON set of query details to a query resource endpoint and get an identifier for the query resource (say it returns a query id of 123)
  • Submit to the get request a query identifier http://some.test/myresource?query_id=123
  • Delete the query resource 123

I see the pure method much more overhead than using PUT with query resource data in the body.

二智少女猫性小仙女 2024-08-24 14:18:18

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

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

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

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


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

I thought that the whole point in REST was to work on "documents" (or something alike). The URI part of a request is there to identify uniquely the resource to work on. The body part in contrast is there for the "contents" part of the document.

Hence, use the "body" part of the request.

Also note that the semantics of a "GET" request isn't supposed to be used for "PUTTING" or "POSTING" documents (comment in relation to your "query" example above which seems to "create" an object).

In any case, as you have pointed out, the URI part is limited (for good reason I am sure).


If you are concerned with caching, then the use of ETag/Last-Modified fields (in conjunction with "conditional GET" helps for this purpose.

回心转意 2024-08-24 14:18:18

这是第二个选项的细微变化。为自己创建一个名为 QueryMaker 的处理器资源。将您的参数发布给它,让它将您重定向到将返回结果的临时查询资源。

POST /QueryMaker
Body: Big Json representation of parameters

303: See Other
Location: http://example.org/TemporaryQueries/123213

Here is a slight variation on your second option. Create yourself a processor resource called QueryMaker. POST your parameters to it and let it redirect you to a temporary query resource that will return your results.

POST /QueryMaker
Body: Big Json representation of parameters

303: See Other
Location: http://example.org/TemporaryQueries/123213
奢华的一滴泪 2024-08-24 14:18:18

如果您使用 GET 请求发送大型对象,则说明您没有正确使用 REST。

  • 应该使用 GET 来检索
    资源(通过某种独特的
    标识符)
  • POST 应该用于
    创建资源(内容
    在体内)
  • PUT 应该用于
    更新资源(使用
    正文中的内容)
  • DELETE 应该用于删除资源

如果您遵循这些准则,您将永远不必拥有过长的 URI。

一些最佳实践 REST 指南如下:http://www. xml.com/pub/a/2004/08/11/rest.html

If you are using a GET request to send large objects, you are not using REST correctly.

  • GET should be used for retrieving
    resources (via some sort of unique
    identifier)
  • POST should be used for
    creating resources (with the contents
    in the body)
  • PUT should be used for
    updating a resource (with the
    contents in the body)
  • DELETE should be used for deleting a resource

If you follow these guidelines you will never have to have overly long URIs.

Some best practice REST guidelines are here: http://www.xml.com/pub/a/2004/08/11/rest.html

场罚期间 2024-08-24 14:18:18

开放网络上 URL 长度的最大限制实际上是 IE,它将 URL 长度限制为 2083 个字符

一些代理(例如,除了最新版本的 Squid 之外的所有代理)会将其限制为大约 4k,尽管这是 慢慢向 8k 迈进

您的#2 解决方法是一个好方法,具体取决于您的用例。

在 GET 上发送主体可能被某些实现允许,而被其他实现禁止,因此对于互操作性和理论原因来说这不是一个好主意。最重要的是,缓存如何知道使用什么作为密钥?

The biggest limitation of URL lengths on the open Web is actually IE, which constraints them to 2083 characters.

Some proxies (e.g., all but the most recent versions of Squid) will limit them to about 4k, although this is moving towards 8k slowly.

Your #2 workaround is a good approach, depending on your use case.

Sending bodies on GETs may be allowed by some implementations, and disallowed by others, so it's a bad idea for interoperability as well as theoretical reasons. Most importantly, how will a cache know what to use as a key?

夏花。依旧 2024-08-24 14:18:18

难道您不能只使用 GET 请求正文发送大 JSON 数据,而不是创建临时资源吗?

虽然它不是 100% 完全正确,但我发现它可以很好地与 firefox、IE 和 IMO 配合使用,但查询字符串不够优雅,并且通常会公开不属于 URI 的实现细节。如果您需要最新数据,请确保添加缓存破坏器查询字符串参数,因为服务器在确定是否可以返回缓存响应时将忽略该数据。

有关在 GET 请求正文中填充数据的优缺点的讨论,请参阅此处

Can't you just send the big JSON data with the GET request body, instead of creating the temp resource?

Although it's not 100% kosher, i've found it works nicely with firefox and IE and IMO, the querystring is inelegant and usually exposes implementation details that don't belong in the URI. Just make sure to add a cache buster querystring parameter if you need up-to-date data because the server will ignore the data when determining whether it can return a cached response.

See here for a discussion of pros and cons of stuffing data in the GET request body.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文