把 cURL 转成 fetch、Axios 或 Python,别丢了关键请求头
cURL 命令是复现一个 HTTP 请求最可靠的方式,但也是把它塞进代码里最糟糕的方式。在 cURL、fetch、Axios 和 Python requests 之间转换是机械的,但微妙的行为就藏在这机械的部分里:请求头、body 编码,以及每个客户端默默施加的默认值。
cURL 命令是分享 HTTP 请求的标准方式。你从 DevTools、同事或厂商文档里复制它,它就能精确复现请求。问题出在你把这条命令当成 API 调用粘进源代码时。cURL 是调试格式,不是客户端库,而转换到 fetch、Axios 或 Python requests 的过程,正是请求悄悄改变行为的地方。
转换后能保留什么
方法、URL、请求头和 body 在细致的转换中都能保留。这些是服务端真正依赖的部分,好的转换器原样保留。Authorization 头、Content-Type、自定义 X- 头,以及任何形式的 body(JSON、form-encoded、multipart)都应原样出现在输出里。
Cookie 是第一个要查的。从浏览器会话抓到的 cURL 命令常带着含 session token 的 Cookie 头。把它粘进应用代码等于硬编码了一个会过期的会话。转换器保留这个头是对的(为了复现),但发布前你得把它换成应用自己的认证流程。
每个客户端默默加的请求头
cURL 发一小撮默认头,包括 User-Agent: curl/x.y.z 和 Accept: */*。浏览器里的 fetch 发一大堆,包括浏览器 User-Agent、Accept-Language,以及服务端可能用于安全检查的 Sec-Fetch-* 头。Axios 发自己的 User-Agent,Python requests 又是另一个。
这很重要,因为有些服务端按这些头分流。一个在 cURL 里工作的请求,在 fetch 里可能失败,因为服务端对浏览器请求处理不同,或因为 Sec-Fetch-Site 头触发了 CSRF 检查。当转换后的请求和原 cURL 行为不同时,先比默默加的头,而不是 body。
body 编码是转换出问题的地方
带 -d '{"a":1}' 的 cURL 命令默认把 body 当 application/x-www-form-urlencoded 发,即使内容是 JSON。服务端可能因为无视 Content-Type 解析 JSON 而接受它,也可能拒绝。转到 fetch 时,自然的翻译是 body: JSON.stringify({a: 1}) 加 Content-Type: application/json 头,这是一个和原请求不同的请求。
表单数据同样如此。带多个 -d 标志的 cURL 发 form-encoded 数据。因为看起来像键值对就转成 JSON body,是不同的请求。细致的转换器保留原始编码:表单还是表单,JSON 还是 JSON,Content-Type 头和 body 匹配。
Multipart 最难。带 -F 标志的 cURL 上传 multipart 表单数据,可含文件。转成 fetch 需要 FormData 对象,转成 Python 需要 files= 和 data= 参数。如果转换器丢了一个文件字段或把它当成字符串,上传就坏了。Multipart 转换永远要和原请求比对后再信任。
重定向和超时默认值
cURL 只在带 -L 时跟随重定向。fetch 默认不按同样方式跟随,redirect: 'follow' 选项改变行为。Axios 在 Node 默认跟随、在浏览器不跟随。Python requests 默认跟随。
这些默认值意味着转换后的请求在 301 或 302 上可能行为不同。如果原 cURL 靠 -L 跟到登录页,转换后的代码可能停在重定向处返回 302 而不是最终页面。原命令用了 -L 时,显式检查重定向行为。
超时类似。cURL 没有默认超时,服务端不响应就一直挂。fetch 也没默认超时,但浏览器网络栈可能施加一个。Axios 和 Python requests 有可配置超时但没默认值。原命令挂住的话,转换后的代码也会挂,除非你加超时。
什么时候转换,什么时候重写
需要把某个具体请求在代码里复现时,转换是对的,典型场景是一次性脚本或测试。转换后的代码保留精确请求(含所有头),所以服务端看到和 cURL 一样的东西。
为 API 构建客户端时,重写是对的。转换后的代码带着调试残留:硬编码 token、浏览器专属头、以及抓 cURL 的人选的 body 编码。真正的客户端需要自己的认证、错误处理和重试逻辑。用转换后的代码理解 API 期望什么,再从头写客户端。
本站 Request 工具处理机械转换,保留请求头、body 和认证,这样你能把 cURL 原件和 fetch、Axios、Python 输出并排比较,看清到底变了什么。比较才是有价值的部分,因为它在生产 bug 出现前把默默的差异亮给你看。
主要参考资料
用于核对本文技术细节的标准与官方文档。
把 cURL 转成 fetch、Axios 或 Python
本站的 Request 工具解析 cURL 命令,输出 fetch、Axios 或 Python requests 代码,保留请求头、body 和认证。全部在浏览器里运行,命令不会离开你的机器。
打开 Request 工具相关文章
继续阅读同一主题领域的实践指南。
Node 生产 Dockerfile 里到底该有什么,不该有什么
网上大多数 Node Dockerfile 都把 node_modules 直接拷进镜像、用 root 运行、最后产出一个 900 MB 的层。本文只讲那几个真正影响构建时间、镜像体积和运行时安全的决定:基础镜像、多阶段构建、依赖层缓存、NODE_ENV 陷阱,以及为什么你的 docker-compose 不该照搬生产。
在用户之前发现缺失的翻译键和插值参数不匹配
缺失的翻译键会把原始键路径直接渲染给用户,插值参数不匹配会渲染出空串或崩溃。这两者在评审中都容易漏,因为开发者的语言包永远有全部键。本文讲如何结构化比较 locale JSON 文件、找出缺失键,并在发布前抓住参数不匹配。
能真正压测 UI 的 mock 数据(而不是只把页面填满)
大多数 mock 数据是同一行复制十遍、只换个 id。它填满页面,却什么都测不到。本文讲如何生成能压测布局边界、长名字、缺失字段、空状态,以及会破坏格式化代码的日期和数字格式的 mock 数据,并通过字段推断让一个 JSON 样本一步变成贴近真实的数据集。