【问题标题】:GET HTTP request payloadGET HTTP 请求负载
【发布时间】:2013-05-03 13:41:13
【问题描述】:

我正在设计一个 API,我想知道在 GET 请求上发送 JSON 有效负载是否可以?

在这个问题Payloads of HTTP Request Methods,我们可以根据this link找到:

  • 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" }
            }
        }
    }
}
'

如果这个受欢迎的图书馆做到了,没有人抱怨,那么也许我也可以这样做?

顺便说一句,我想知道混合 queryString 参数和 JSON 负载是否可以? 就像这个 ElasticSearch 查询一样。如果是这样,是否有规则让我们知道哪些参数应该是 queryString 参数或有效负载参数?


在这里我们可以阅读: HTTP GET with request body

Roy Fielding 关于在 GET 请求中包含正文的评论。

是的。换句话说,任何 HTTP 请求消息都允许包含一个 消息体,因此必须考虑到这一点来解析消息。服务器 但是,GET 的语义受到限制,因此主体(如果有) 对请求没有语义意义。解析的要求 与方法语义的要求是分开的。

所以,是的,您可以使用 GET 发送正文,但不,它对 这样做。

这是 HTTP/1.1 分层设计的一部分,将会变得清晰 再次对规范进行分区(正在进行中)。

....罗伊

然后我真的不明白为什么它从来没有用,因为在我看来,将复杂的查询发送到不适合 queryParam 或 matrixParam 的服务器是有意义的。 我认为 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 请求中发送有效负载。老实说,我什至没有意识到你可以用 curl 做到这一点。

标签: java api http get elasticsearch


【解决方案1】:

让 GET 响应因请求正文而异会破坏缓存。不要去那里。

【讨论】:

  • 这是一个不需要缓存的 API,因为它由标识客户端的 OAuth2 标头进行上下文化。不同的客户端可以对同一个资源 URI 有不同的表示,所以我不能基于资源 URI 进行缓存
  • 所有中介机构/图书馆都知道这一点吗?
  • 肯定是因为他们需要访问允许他们操纵用户帐户的 OAuth2 令牌。因此 /profile 资源是客户端拥有 OAuth2 令牌(作为标头给出)的用户配置文件
  • 既然您提到了 ElasticSearch,那么每个带有 /_search 和 /_count 等端点的 GET 请求都有一个 POST 对应项。
【解决方案2】:

另请参阅:HTTP GET with request body - 了解更多详情。

要点是:是的,您可以,但出于各种原因,您可能不应该这样做,包括:

  • 您可能会忽略 HTTP 规范建议(您可能想要 POST)
  • 您可能会引入缓存问题
  • 就 REST API 而言,这直观

【讨论】:

    【解决方案3】:

    Google App Engine 是一种流行的网络框架,它使用一个特殊的 url 获取库,它是 does not support making HTTP GET requests with a payload。因此,如果您希望您的 API 能够覆盖 Google App Engine 用户,那么我不建议您要求这种行为。

    我用谷歌打开了an issue regarding this

    【讨论】:

    • 请注意,如果您需要发出GET 请求,您可以在source 查询字符串参数中对请求的主体进行urlencode,而不是与请求的主体一起发送。
    【解决方案4】:

    仅仅因为你可以做某事,并不意味着你应该。很抱歉,如果这听起来令人恼火的重复,但关于标准的事情是它们是标准 - 而 HTTP 是最成熟的标准之一。它并不完美,很多人都想改变很多东西,但事实上几乎每个人仍在使用 URL 参数来处理诸如此类的用例,这足以表明没有现在任何可靠的替代品。

    speedplane 和 Julian Reschke 的回答给出了两个具体示例,说明如果您依赖带有 body/payload 的 GET 请求,将会出现问题。如果您愿意,您可以以与其他人不同的方式编写您的应用程序,但网络是一个可能比平时更重视标准的领域。我知道成为开拓者很诱人,但恕我直言,请考虑存在多少网站,以及有多少网络程序员正在构建和维护它们。如果有明确更好的方法,您现在很可能会看到它在生产中得到广泛使用。

    标准更改/采用缓慢,因为必须有太多人同意这些标准才能发挥作用。你说有应用程序违反规则是正确的,但你会注意到它们已经让人们头疼,并且在某些情况下需要解决方法/冗余措施,正如 Aetherus 所提到的在他们对另一个答案的评论中。在这样的问题上,我倾向于走阻力最小的道路。不过,如果你真的想这样做,我相信你可以做到。

    【讨论】:

    • 我怀疑很大程度上取决于预计谁会使用 API。如果唯一的消费者是您自己,并且您编写在端点上运行的代码,我怀疑您使用 GET 是安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多