使用JavaScript(XMLHttpRequest)发送带有请求体的GET请求

24

我必须与一个从GET请求的body中取参数的API进行交互。我知道这可能不是最好的做法,但这就是API构建的方式。

当我尝试使用 XMLHttpRequest 构建查询时,似乎负载根本没有被发送。您可以运行此代码并查看网络选项卡;请求已发送,但没有正文(在最新版本的Chrome和Firefox中测试):

const data = {
  foo: {
    bar: [1, 2, 3]
  }
}
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://my-json-server.typicode.com/typicode/demo/posts')
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
xhr.send(JSON.stringify(data))

诸如axios之类的库是基于XMLHttpRequest构建的,因此它们也无法工作……

在JavaScript中有没有实现这一点的方法?

1个回答

28
不,JavaScript中不可能发送带有主体的GET请求。
引用区块中提到,“貌似负载根本没有发送”是正确的。这在规范中得到了定义:该规范中
“send(body)方法必须执行以下步骤:”
如果请求方法为GET或HEAD,则将主体设置为null。
此外,Fetch API 中的请求也不允许包含主体。从该规范中可以看到:
如果init ["body"]存在且非null或inputBody非null,并且请求的方法是GET或HEAD,则抛出TypeError。
最好的解决方案是修复API。
如果不能修复API,可以添加一个服务器端脚本作为代理,将请求传递到API。然后,您可以使用URL中的数据调用此脚本以带有GET请求,而不是使用带有主体的POST请求。只要所选语言支持,此脚本就可以使用带有主体的GET请求。

35
为了不招惹HTTP之神,但就记录而言,在2019年,这个规范似乎有些愚蠢。我经常想在请求中发送一些有效载荷。这个有效载荷可能非常大,因此我不希望它出现在URL中。从语义上讲,我正在进行一个GET请求(“给我一些东西,这是我想要的详细信息,不要创建任何东西。”),而这个规范要求我将其改为POST/PUT请求或使用其他一些技巧。 - John Carrell
2
@JohnCarrell HTTP规范实际上并没有禁止这样做:“GET请求消息中的有效载荷没有定义的语义;在GET请求中发送有效载荷主体可能会导致某些现有的实现拒绝该请求。” https://tools.ietf.org/html/rfc7231#section-4.3.1 - Sergey
2
我已经争论了十多年,这些框架是有问题的。REST > HTTP。如果我想要表示我想要获取某些数据,给定某些参数,并且这些参数不适合于查询字符串,无论是因为序列化简单性、大小、字符集、安全性还是其他任何原因,我都应该能够通过Body将这些参数传递到“GET”端点。请求数据(即使基于参数)通过调用“PUT”或“POST”是不符合RESTful的正确方式。(尽管您可以期望它们在其各自的添加/更新操作之后返回数据)。 - Suamere
3
最好的情况是API能够被修复。- API没有出现问题,使用它的框架有问题。 - Suamere
1
使用GET请求体来描述查询的问题在于,由于历史原因,缓存不考虑请求体。使用GET请求描述查询会“污染”请求经过的任何缓存,以至于随后使用不同请求体的GET尝试将返回原始结果。API的观察行为因此变得依赖于网络拓扑结构。这是一个潜在的缺陷。 - eisenpony
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接