GET HTTP请求有效载荷
GET HTTP请求有效载荷
我正在设计一个API,想知道在GET请求中发送JSON负载是否可行?
在这个问题中HTTP请求方法的负载,我们可以根据这个链接找到以下内容:
- HEAD - 未定义的正文语义。
- GET - 未定义的正文语义。
- PUT - 支持正文。
- POST - 支持正文。
- DELETE - 未定义的正文语义。
- TRACE - 不支持正文。
- OPTIONS - 支持正文,但没有语义(可能在将来使用)。
这是否意味着我不应该发送带有负载的GET请求?
这样做会有风险吗?
- 比如一些HTTP客户端库无法发送这样的负载?
- 或者我的Java API代码在某些应用服务器上不可移植?
- 还有其他什么问题吗?
我发现ElasticSearch在GET请求中使用了这样的负载:
$ curl -XGET 'http://localhost:9200/twitter/tweet/_search?routing=kimchy' -d '{ "query": { "filtered" : { "query" : { "query_string" : { "query" : "some query string here" } }, "filter" : { "term" : { "user" : "kimchy" } } } } } '
所以如果这个流行的库这样做而没有人抱怨,那么我也可以这样做吗?
顺便说一下,我想知道是否可以混合使用查询字符串参数和JSON负载?就像ElasticSearch的查询一样。如果可以的话,是否有规则可以知道哪些参数应该是查询字符串参数,哪些参数应该是负载参数?
在这里我们可以读到:
Roy Fielding关于在GET请求中包含正文的评论。
是的。换句话说,任何HTTP请求消息都可以包含一个
消息正文,并且必须解析带有这个正文的消息。然而,对于GET的服务器
语义受限,因此,如果有的话,正文对请求没有语义上的意义。对解析的要求
与方法语义的要求是分开的。
所以,是的,你可以发送带有GET请求的正文,但是,不,这是从来没有用过。
这是HTTP/1.1的分层设计的一部分,在规范分区后会再次变得清晰
(正在进行中的工作)。
....Roy
然后我真的不明白为什么它从来没有用过,因为在我看来,将复杂查询发送到服务器是有意义的,这些查询在查询参数或矩阵参数中不容易适应。
我认为ElasticSearch的API设计者也是这样认为的...
我计划设计一个可以像这样调用的API:
curl -XGET 'http://localhost:9000/documents/inbox?pageIndex=0&pageSize=10&sort=title' curl -XGET 'http://localhost:9000/documents/trash?pageIndex=0&pageSize=10&sort=title' curl -XGET 'http://localhost:9000/documents/search?pageIndex=0&pageSize=10&sort=title' -d '{ "someSearchFilter1":"filterValue1", "someSearchFilter2":"filterValue2", "someSearchFilterList": ["filterValue3","xxx"] ... a lot more ... } '
你觉得这样可以吗?基于上述考虑。
问题:为什么会出现(GET HTTP request payload)这个问题?以及如何解决这个问题。
在这段对话中,提到了在HTTP的GET请求中使用request payload会破坏缓存。但是对于这个API来说,不需要缓存,因为它是由一个OAuth2头部上下文化的。不同的客户端可能对同一个资源URI有不同的表示,所以无法根据资源URI进行缓存。
问题的原因:GET请求中的request payload会破坏缓存,而这个API中需要根据OAuth2头部上下文化来确定资源的表示,无法根据资源URI进行缓存。
解决方法:不使用GET请求中的request payload,可以考虑使用POST请求作为替代。
GET请求不应该包含请求正文(HTTP request payload),这是因为以下原因:
1. 不符合HTTP规范的建议,通常应该使用POST请求来发送包含请求正文的数据。
2. 可能会引起缓存问题,因为GET请求通常会被缓存,而请求正文可能包含会导致缓存失效的信息。
3. 这种做法在REST API中并不直观,使用GET请求应该用于获取资源而不是修改资源。
如果确实需要在GET请求中包含请求正文,可以通过以下解决方法实现:
1. 将请求参数放在URL的查询字符串中,而不是请求正文中。
2. 将请求方法改为POST,因为POST请求可以包含请求正文。
3. 将请求正文的内容进行编码,然后将编码后的内容放在URL的查询字符串中,如下所示:
GET /api/resource?payload=encoded_payload HTTP/1.1
Host: example.com
然而,建议根据实际需求使用合适的HTTP请求方法,遵循HTTP规范,并使用POST请求来发送包含请求正文的数据。
问题的出现原因是Google App Engine使用的url fetch库不支持带有payload的HTTP GET请求。因此,如果你想让你的API能够被Google App Engine的用户使用,那么不建议要求使用这种行为。
解决方法是,如果你需要进行GET请求,可以将请求的body进行urlencode,并将其放在source查询字符串参数中,而不是将其放在请求的body中。
这个问题已经向Google提出了反馈,你可以通过这个链接查看反馈的详情。