调试接口用Postman是挺方便,但服务器上没图形界面,只能用curl。
curl功能强大得离谱,但大部分人只会curl一个URL。这篇总结一下我常用的调试技巧。
基础请求
# GET
curl https://api.example.com/users# 带参数的GET
curl "https://api.example.com/users?page=1&size=10"# POST表单
curl -X POST -d "username=test&password=123" https://api.example.com/login# POST JSON
curl -X POST \-H "Content-Type: application/json" \-d '{"username":"test","password":"123"}' \https://api.example.com/login# 从文件读取body
curl -X POST -d @data.json https://api.example.com/users
查看详细信息
这才是调试的关键。
# 显示响应头
curl -i https://api.example.com/users# 只显示响应头不要body
curl -I https://api.example.com/users# 显示请求和响应的全部信息(最详细)
curl -v https://api.example.com/users
-v输出很有用,能看到:
- DNS解析
- TCP连接
- TLS握手
- 发送的请求头
- 收到的响应头
* Trying 1.2.3.4:443...
* Connected to api.example.com (1.2.3.4) port 443
* TLS handshake...
> GET /users HTTP/2
> Host: api.example.com
> User-Agent: curl/7.68.0
>
< HTTP/2 200
< content-type: application/json
< ...
设置请求头
# 单个Header
curl -H "Authorization: Bearer xxx" https://api.example.com/users# 多个Header
curl -H "Authorization: Bearer xxx" \-H "X-Request-ID: abc123" \-H "Accept: application/json" \https://api.example.com/users# 覆盖默认的User-Agent
curl -A "MyApp/1.0" https://api.example.com/users
处理响应
# 保存响应到文件
curl -o response.json https://api.example.com/users# 用服务器返回的文件名
curl -O https://example.com/file.zip# 只要响应体,用jq格式化(需要安装jq)
curl -s https://api.example.com/users | jq .# 提取某个字段
curl -s https://api.example.com/users | jq '.data[0].name'
-s是静默模式,不显示进度条。
性能分析
这个很实用。排查接口慢的问题时,需要知道时间花在哪了。
curl -w "@curl-format.txt" -o /dev/null -s https://api.example.com/users
curl-format.txt内容:
time_namelookup: %{time_namelookup}s\ntime_connect: %{time_connect}s\ntime_appconnect: %{time_appconnect}s\ntime_pretransfer: %{time_pretransfer}s\ntime_redirect: %{time_redirect}s\ntime_starttransfer: %{time_starttransfer}s\n----------\ntime_total: %{time_total}s\n
输出:
time_namelookup: 0.012s <- DNS解析耗时time_connect: 0.045s <- TCP连接耗时time_appconnect: 0.156s <- TLS握手耗时(HTTPS才有)time_pretransfer: 0.156s <- 准备传输耗时time_redirect: 0.000s <- 重定向耗时time_starttransfer: 0.312s <- 首字节耗时(TTFB)----------time_total: 0.456s <- 总耗时
最有用的是time_starttransfer,也就是TTFB(Time To First Byte),能反映服务端的处理时间。
嫌建文件麻烦,用一行命令:
curl -o /dev/null -s -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\nTotal: %{time_total}s\n" https://api.example.com/users
模拟各种场景
带Cookie
# 发送Cookie
curl -b "session=abc123" https://api.example.com/users# 保存响应的Cookie到文件
curl -c cookies.txt https://api.example.com/login# 用保存的Cookie发请求
curl -b cookies.txt https://api.example.com/users
跟随重定向
# 默认不跟随,加-L跟随
curl -L https://example.com/redirect
指定DNS解析
绕过DNS,直接指定IP:
curl --resolve api.example.com:443:1.2.3.4 https://api.example.com/users
测试新服务器时很有用,不用改hosts。
忽略证书错误
测试环境的自签名证书:
curl -k https://test.internal.com/api
生产环境别用-k。
限速
测试慢网络情况:
# 限制下载速度为100KB/s
curl --limit-rate 100K https://example.com/file.zip
设置超时
# 连接超时5秒
curl --connect-timeout 5 https://api.example.com/users# 整体超时10秒
curl -m 10 https://api.example.com/users
重试
# 失败重试3次
curl --retry 3 https://api.example.com/users# 重试间隔2秒
curl --retry 3 --retry-delay 2 https://api.example.com/users
文件上传
# 上传文件
curl -F "file=@/path/to/file.jpg" https://api.example.com/upload# 带其他参数
curl -F "file=@/path/to/file.jpg" -F "name=test" https://api.example.com/upload# 指定文件类型
curl -F "file=@/path/to/file.jpg;type=image/jpeg" https://api.example.com/upload
代理设置
# HTTP代理
curl -x http://proxy.example.com:8080 https://api.example.com/users# SOCKS5代理
curl --socks5 127.0.0.1:1080 https://api.example.com/users
调试HTTPS
# 显示TLS握手细节
curl -v --trace-ascii - https://api.example.com/users# 指定TLS版本
curl --tlsv1.2 https://api.example.com/users# 查看证书信息
curl -vI https://api.example.com 2>&1 | grep -A 6 "Server certificate"
实用场景
测试接口是否正常
# 只关心状态码
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/health
批量测试
# 测试10次,看平均响应时间
for i in {1..10}; docurl -s -o /dev/null -w "%{time_total}\n" https://api.example.com/users
done
对比两个环境
# 测试环境
curl -s https://test.example.com/api/users | md5sum# 生产环境
curl -s https://api.example.com/users | md5sum
响应一样就md5一样。
生成代码
curl可以直接生成各种语言的代码:
# 转成Python
curl https://api.example.com/users --libcurl output.py# 或者用在线工具把curl命令转成代码
常用alias
加到/.bashrc或/.zshrc:
# 格式化JSON响应
alias curljson='curl -s | jq .'# 只看状态码
alias curlcode='curl -s -o /dev/null -w "%{http_code}\n"'# 带详细信息
alias curlv='curl -v'# 带性能信息
alias curltime='curl -o /dev/null -s -w "DNS: %{time_namelookup}s | Connect: %{time_connect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s\n"'
用起来:
curljson https://api.example.com/users
curlcode https://api.example.com/health
curltime https://api.example.com/users
curl的参数太多,没必要都记住。知道有这些功能,用的时候来查就行。
跨服务器调试时,如果网络不通,我一般用星空组网先把几台机器串起来,然后curl各种测。