把 curl 命令改写成 fetch 时,最容易踩的 6 个坑
接口文档里的 curl 一跑就通,改成 JavaScript fetch 却报错?逐个讲清楚请求方法、Content-Type、查询参数、认证、重定向和 CORS 的差异。
几乎所有 API 文档都会给出 curl 示例。在终端里一跑就通,可一改写成 fetch,就开始出现 400、401 或者 CORS 报错。原因通常是 curl 默认帮你做了一些事情,而 fetch 没有。
1. -d 会自动把请求变成 POST
curl https://api.example.com/items -d 'name=book'
这条命令没有写 -X POST,但只要带了 -d,curl 就会发送 POST 请求。改写时别忘了:
await fetch('https://api.example.com/items', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'name=book',
});
2. -d 默认的 Content-Type 是表单,不是 JSON
很多人会这样发 JSON:
curl https://api.example.com/items -d '{"name":"book"}'
此时 curl 发送的 Content-Type 是 application/x-www-form-urlencoded,不少服务端会因此解析失败。正确写法是显式加请求头,或者使用较新版本 curl 支持的 --json 参数:
curl https://api.example.com/items \
-H 'Content-Type: application/json' \
-d '{"name":"book"}'
对应的 fetch 也要设置请求头,并用 JSON.stringify 序列化:
await fetch('https://api.example.com/items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'book' }),
});
3. -G 会把数据放进 URL
curl -G https://api.example.com/search -d q=你好 -d page=2
加了 -G 后,-d 的内容会拼接到 URL 上,变成 GET 请求。在 fetch 里推荐用 URLSearchParams 拼参数,它会自动处理中文和特殊字符的编码:
const url = new URL('https://api.example.com/search');
url.search = new URLSearchParams({ q: '你好', page: '2' }).toString();
await fetch(url);
想看某个参数编码后的样子,可以用 URL 编解码 对照一下。
4. -u 是 Basic 认证
curl -u admin:secret https://api.example.com/me
fetch 没有对应的参数,需要自己生成 Authorization 请求头,内容是 用户名:密码 的 Base64 编码:
await fetch('https://api.example.com/me', {
headers: { Authorization: 'Basic ' + btoa('admin:secret') },
});
注意 btoa 只支持 Latin-1 字符,如果用户名或密码里有中文,需要先转成 UTF-8 字节再编码。Base64 编解码 就是按 UTF-8 处理的。
5. 重定向和压缩:方向正好相反
- curl 默认不跟随重定向,要加
-L;fetch默认跟随。 - curl 加
--compressed才会请求并解压 gzip/br;浏览器和 Node.js 的fetch会自动处理。
所以 -L 和 --compressed 改写时通常可以直接删掉。
6. 浏览器里的 CORS 和受限请求头
这是最常见、也最让人困惑的一点:同样的请求,curl 能成功,在浏览器里却失败。
- 浏览器会执行同源策略。目标服务器没有返回允许跨域的
Access-Control-Allow-Origin等响应头时,请求会被浏览器拦下;curl 和服务端代码不受这个限制。 - 浏览器不允许脚本设置某些请求头,比如
Cookie、Host。curl 里的-b(Cookie)在前端无法照搬。 - curl 的
-k(跳过证书校验)在浏览器里没有对应选项。
解决办法通常是:让服务端配置 CORS,或者把请求放到自己的后端或 serverless 函数里转发。
不想手改?
curl 转代码 会自动处理上面这些规则:识别 -d、--json、-G、-u、-F、多行命令等,一键生成 JavaScript fetch、Python requests 或 Go 代码。转换完成后,再根据运行环境(浏览器还是服务端)检查一下 CORS 和认证方式即可。