我有REST服务,应该通过GET接收非常长的查询。比方说,我想用许多地理坐标来查询服务,以找出有关所有这些坐标的信息。
1)我的第一个想法是使用servlet容器的长URI和increase the max URI length。
看起来像这样:
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请求的主体进行查询是一个好主意,并且共识是:不。甚至罗伊菲尔丁说这是bad idea。
4)另一种方法可能是将POST解释为“创建查询结果资源”并在请求后删除此资源。但我认为这不是RESTful而是一个坏主意。
使用GET请求处理大型查询是否有更好的方法?
答案 0 :(得分:3)
我认为REST中的重点是处理“文档”(或类似的东西)。请求的URI部分用于标识唯一要处理的资源。相反,正文部分是文档的“内容”部分。
因此,请使用请求的“正文”部分。
另请注意,“GET”请求的语义不应该用于“PUTTING”或“POSTING”文档(与上面的“查询”示例相关的评论似乎是“创建”一个对象)
无论如何,正如您所指出的,URI部分是有限的(我确信这是有充分理由的。)
如果您关注缓存,那么使用ETag / Last-Modified字段(与“条件GET”一起使用有助于实现此目的。
答案 1 :(得分:3)
如果您使用GET请求发送大型对象,则表明您没有正确使用REST。
如果您遵循这些准则,则永远不会有过长的URI。
这里有一些最佳做法REST指南:http://www.xml.com/pub/a/2004/08/11/rest.html
答案 2 :(得分:3)
使用PUT
。
为什么呢?原因如下:
PUT
'可以更新资源,并不意味着它会或者必须改变资源的基本状态。PUT
的API端不应创建新的资源标识符(url)。是的,从技术上讲,PUT
可以使用客户端指定的标识符,但在这种情况下,您将访问现有资源。PUT
就像GET
一样,它应该是幂等的,这意味着请求的结果总是相同的,无论你多久调用它,它都没有副作用。< / LI>
PUT
表示您将资源数据放入现有资源。就文档/博客文章世界中的文章或帖子而言,就像将某个文档的新版本上载到现有资源URL一样。如果您将相同的修订上载到同一个URL,则您获取的资源中不应更改任何内容。
在您的情况下,地理位置数据是您上传的一些新资源数据,每次发出相同请求时,您获得的结果应该相同。
对请求使用GET
动词的更纯粹的方法可能是:
123
的查询ID)http://some.test/myresource?query_id=123
123
我认为纯方法比在主体中使用PUT
和查询资源数据要花费更多的开销。
答案 3 :(得分:2)
您的第二个选项略有不同。创建一个名为QueryMaker的处理器资源。将参数发布到它并让它重定向到一个临时查询资源,该资源将返回结果。
POST /QueryMaker
Body: Big Json representation of parameters
303: See Other
Location: http://example.org/TemporaryQueries/123213
答案 4 :(得分:0)
开放Web上URL长度的最大限制实际上是IE,constraints them to 2083 characters。
某些代理(例如,除了最新版本的Squid之外的所有代理)都会将它们限制为大约4k,尽管这是moving towards 8k slowly。
根据您的使用情况,您的#2解决方法是一种很好的方法。
某些实现可能允许在GET上发送正文,而其他人不允许这样做,因此对于互操作性和理论原因来说,这是一个坏主意。最重要的是,缓存如何知道将什么用作密钥?
答案 5 :(得分:-1)
你不能只用GET请求体发送大的JSON数据,而不是创建临时资源吗?
虽然它不是100%kosher,但我发现它与firefox以及IE和IMO很好地协同工作,查询字符串不够优雅,并且通常会暴露不属于URI的实现细节。如果您需要最新数据,请确保添加cache buster querystring参数,因为服务器在确定是否可以返回缓存响应时会忽略数据。
有关GET请求正文中填充数据的优缺点的讨论,请参阅here。