如何使用Fetch API发送与可正常运行的curl命令等效的请求体数据?
我有一段可以正常运行的curl命令,导入Postman后能成功获取响应:
curl --request POST \ --data "grant_type=password" \ --data "username=test" \ --data "password=xyz1234" \ --data "scope=write" \ --data "client_id=test" \ --data "client_secret=test12" \ "https://example.com/access_token"
但我用JavaScript的Fetch API发送请求时,却得到了400错误响应。我的Fetch代码如下:
const response = await fetch ('https://example.com/access_token', { 'credentials' : 'include', method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ grant_type:'password',username:'test',password:'xyz1234',scope:'write',client_id:'test',client_secret:'test12'}), })
从Chrome开发者工具复制的等效curl是这样的,明显和原curl格式不同:
curl --request POST \ --data-raw '{"grant_type":"password","username":"test","password":"xyz1234","scope":"write","client_id":"test","client_secret":"test12"}' "https://example.com/access_token"
我怀疑是请求体格式不对导致的错误,请问怎么用Fetch API发送和原curl等效的请求?
嘿,这个问题很好解决!你遇到的400错误核心原因是请求体的格式不匹配:
你的原curl命令发送的是application/x-www-form-urlencoded格式的表单数据(多个--data参数会自动拼接成这种格式,Content-Type默认就是这个),但你的Fetch代码却把数据转成了JSON格式,还设置了Content-Type: application/json,服务器无法解析这种格式的请求体,所以返回了400错误。
要让Fetch请求和原curl完全等效,你需要改成发送表单格式的数据,这里有两种简单的实现方式:
方法1:使用URLSearchParams(推荐)
URLSearchParams对象会自动帮你处理表单数据的编码,而且Fetch会自动设置正确的Content-Type请求头(不需要手动添加,当然手动加也没问题):
const response = await fetch('https://example.com/access_token', { credentials: 'include', method: 'POST', body: new URLSearchParams({ grant_type: 'password', username: 'test', password: 'xyz1234', scope: 'write', client_id: 'test', client_secret: 'test12' }) });
方法2:手动拼接表单字符串
如果你想手动控制数据格式,可以直接拼接成key=value&key2=value2的字符串形式,同时手动设置Content-Type:
const response = await fetch('https://example.com/access_token', { credentials: 'include', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'grant_type=password&username=test&password=xyz1234&scope=write&client_id=test&client_secret=test12' });
这样修改后,你再去Chrome开发者工具复制等效curl,就会看到它和你最初的可运行curl命令完全一致了,服务器也能正确解析请求体,不会再返回400错误啦。
内容的提问来源于stack exchange,提问作者Karan Nayyar

