cURL使用指南
curl从入门到进阶:一个HTTP工具控的使用指南
最开始接触curl的时候,我觉得这玩意儿也就是个发HTTP请求的命令行工具,能有多复杂?后来真正用起来才发现,这工具简直就是个宝藏。
为啥我离不开curl?
现在抓包工具和API测试工具一大把,像Postman、Insomnia这些GUI工具不是更方便吗?但还是特别依赖curl,主要有这么几个原因:
无处不在 你说Postman好用是吧?行,你现在SSH到服务器上,Postman呢?curl几乎是所有Linux发行版的标配,包括你的MacOS。Windows...好吧,现在WSL也自带curl了。
脚本化 这才是关键。GUI工具咋写到脚本里?curl命令可以直接复制到shell脚本中,还能用管道跟其他命令组合,简直不要太爽。
可调试性 遇到问题的时候,curl的调试信息相当详细。-v参数一开,从DNS解析到TLS握手,从请求头到响应体,一切尽在掌握。
灵活性 这个说来话长...且听我细细道来。
curl基础操作
别急着看那些复杂的参数。先从最基础的开始:
# 最简单的GET请求
curl http://example.com
# 保存响应到文件
curl -o response.txt http://example.com
# 显示详细信息
curl -v http://example.com
等等,你可能会问,为啥不用wget?wget确实也不错,特别是下载文件的时候。但curl的强项在于它对HTTP协议的完整支持。
HTTP请求那些事
curl最常用的场景当然是发送各种HTTP请求了。我们先看看基本的HTTP方法:
# POST请求
curl -X POST http://api.example.com/create
# 带数据的POST
curl -X POST -d "name=test&age=25" http://api.example.com/create
# JSON格式的POST
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"test","age":25}' \
http://api.example.com/create
说到这儿,不得不提一个我经常踩的坑。你猜怎么着?-d参数会自动设置Content-Type为application/x-www-form-urlencoded。要发送JSON,必须手动设置header。
请求头的艺术
HTTP请求头,这可是个有意思的话题。
# 设置单个header
curl -H "User-Agent: Mozilla/5.0" http://example.com
# 设置多个header
curl -H "User-Agent: Mozilla/5.0" \
-H "Accept: application/json" \
-H "Authorization: Bearer token123" \
http://example.com
有时候我会写个函数把常用的header组合起来:
function api_call() {
local url=$1
curl -H "Authorization: Bearer $API_TOKEN" \
-H "Accept: application/json" \
-H "X-Custom-Header: value" \
"$url"
}
文件上传:这事儿没那么简单
上传文件,看似简单,但curl支持好几种方式:
# 最基本的文件上传
curl -F "[email protected]" http://example.com/upload
# multipart/form-data方式
curl -F "[email protected]" \
-F "name=vacation" \
http://example.com/upload
# 直接发送文件内容
curl --data-binary @file.txt http://example.com/upload
说个有意思的事,有次我在调试文件上传时,发现用-F上传的文件,curl会自动添加一个filename参数。这在某些场景下可能会导致服务端解析错误。解决方法是显式指定filename:
curl -F "[email protected];filename=photo.jpg" http://example.com/upload
认证那些事儿
安全永远是个大话题。curl支持各种认证方式:
# Basic认证
curl -u username:password http://example.com
# OAuth Bearer Token
curl -H "Authorization: Bearer token123" http://example.com
# 证书认证
curl --cert client.pem --key key.pem https://example.com
顺带说一句,如果你经常需要处理自签名证书,可以用-k参数跳过证书验证:
curl -k https://self-signed.example.com
但是,这招要慎用。在生产环境跳过证书验证?这简直就是在裸奔。
调试技巧
这才是我最喜欢curl的地方。当你遇到问题时,curl提供了强大的调试能力:
# 显示通信过程
curl -v http://example.com
# 只显示header
curl -I http://example.com
# 显示响应时间
curl -w "\nTime: %{time_total}s\n" http://example.com
特别是-w参数,可以格式化输出各种指标:
curl -w @- http://example.com <<'EOF'
time_namelookup: %{time_namelookup}\n
time_connect: %{time_connect}\n
time_appconnect: %{time_appconnect}\n
time_pretransfer: %{time_pretransfer}\n
time_redirect: %{time_redirect}\n
time_starttransfer: %{time_starttransfer}\n
----------\n
time_total: %{time_total}\n
EOF
性能测试
虽然curl不是专门的性能测试工具,但简单测试一下还是够用的:
# 测试10次请求
for i in {1..10}; do
curl -w "%{time_total}\n" -o /dev/null -s http://example.com
done
不过说实话,真要做性能测试还是用ab或者wrk这样的工具比较靠谱。
cookie的处理
cookie这东西,有时候挺烦人的:
# 保存cookie
curl -c cookies.txt http://example.com
# 使用已保存的cookie
curl -b cookies.txt http://example.com
# 设置特定cookie
curl -b "session=123" http://example.com
有个小技巧:如果你要调试web应用,可以先用浏览器登录,然后导出cookie给curl用:
# 从Chrome导出的cookie文件转换成curl格式
# 需要先安装cookies.txt Chrome扩展
curl -b cookies.txt http://example.com
代理使用
在国内,代理可能是个刚需:
# HTTP代理
curl -x proxy.example.com:3128 http://target.com
# SOCKS5代理
curl --socks5 127.0.0.1:1080 http://target.com
碰到过一个坑:如果代理需要认证,直接在URL里带用户名密码是不行的,要用-U参数:
curl -x proxy.example.com:3128 -U user:pass http://target.com
重定向处理
curl默认不跟随重定向,需要手动指定-L参数:
curl -L http://example.com
有时候你可能想看看重定向的过程:
curl -vL http://example.com
高级特性
说实话,curl的高级特性太多了,我自己都没用过几个。但有些确实挺有用:
1. URL编码
# 自动处理URL中的特殊字符
curl --url-query "name=John Doe" http://example.com
2. 范围请求
# 下载文件的部分内容
curl -r 0-1024 http://example.com/big-file
3. 多URL处理
# 同时请求多个URL
curl http://site1.com http://site2.com
# 从文件读取URL
curl -K urls.txt
4. 压缩处理
# 支持gzip压缩
curl --compressed http://example.com
curl与Shell的配合
curl最强大的地方在于它可以完美地融入Shell脚本中:
# 处理响应
response=$(curl -s http://api.example.com)
echo $response | jq .name
# 条件判断
if curl -s -o /dev/null -w "%{http_code}" http://example.com | grep -q "200"; then
echo "Site is up!"
fi
# 批量处理
cat urls.txt | while read url; do
curl -s "$url" >> results.txt
done
RESTful API测试
虽然现在各种API测试工具层出不穷,但我还是喜欢用curl测试API:
# GET
curl -s http://api.example.com/users | jq .
# POST
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"test"}' \
http://api.example.com/users
# PUT
curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name":"updated"}' \
http://api.example.com/users/1
# DELETE
curl -X DELETE http://api.example.com/users/1
配合jq使用简直完美:
# 提取特定字段
curl -s http://api.example.com/users | jq '.[] | select(.age > 30) | .name'
安全相关的特性
安全永远是个大话题,curl在这方面也有不少特性:
1. 证书处理
# 指定CA证书
curl --cacert ca.pem https://example.com
# 使用客户端证书
curl --cert client.pem --key key.pem https://example.com
2. SSL/TLS选项
# 指定SSL版本
curl --tlsv1.2 https://example.com
# 显示证书信息
curl -vI https://example.com 2>&1 | grep "SSL certificate"
3. 密码保护
# 从环境变量读取密码
curl -u username:"$API_KEY" http://example.com
错误处理
这个很重要,特别是在脚本中使用curl的时候:
# 失败时显示错误信息
if ! curl -f http://example.com; then
echo "Request failed!"
exit 1
fi
# 超时控制
curl --connect-timeout 5 --max-time 10 http://example.com
一个实用的错误处理函数:
function curl_with_retry() {
local url=$1
local retries=3
local wait=5
local timeout=10
for i in $(seq 1 $retries); do
if curl -sf --connect-timeout $timeout "$url"; then
return 0
fi
echo "Request failed, retry $i/$retries"
sleep $wait
done
return 1
}
性能优化技巧
虽然curl本身已经够快了,但还是有一些优化空间:
1. DNS优化
# 禁用DNS缓存
curl --dns-servers 8.8.8.8 http://example.com
# 强制IPv4
curl -4 http://example.com
2. 连接复用
# 开启keep-alive
curl --keepalive-time 60 http://example.com
3. 压缩传输
# 启用压缩
curl --compressed http://example.com
常见问题和解决方案
说说我经常碰到的一些问题:
1. 证书问题
# 临时解决方案(不推荐)
curl -k https://example.com
# 正确的解决方案
curl --cacert /path/to/certificate.pem https://example.com
2. 编码问题
# 处理特殊字符
curl -G --data-urlencode "q=search term" http://example.com/search
3. 重定向循环
# 限制重定向次数
curl -L --max-redirs 5 http://example.com
curl配置文件
说实话,我很少用curl的配置文件,但确实挺有用的:
# ~/.curlrc
# 默认选项
--compressed
--location
--max-time 30
--retry 3
--retry-delay 2
实用场景示例
来看几个我经常用到的场景:
1. API健康检查
#!/bin/bash
# 一个简单的API健康检查脚本
CHECK_URLS=(
"http://api1.example.com/health"
"http://api2.example.com/health"
)
for url in "${CHECK_URLS[@]}"; do
response=$(curl -s -w "%{http_code}" -o /dev/null "$url")
if [ "$response" = "200" ]; then
echo "✅ $url is healthy"
else
echo "❌ $url returned $response"
fi
done
这个脚本我基本每天都在用。特别是在部署新服务的时候,总得确保服务是真的起来了。
2. 接口性能分析
#!/bin/bash
# API延迟测试脚本
format='{
"time_dns": "%{time_namelookup}",
"time_connect": "%{time_connect}",
"time_ssl": "%{time_appconnect}",
"time_pretransfer": "%{time_pretransfer}",
"time_redirect": "%{time_redirect}",
"time_starttransfer": "%{time_starttransfer}",
"time_total": "%{time_total}",
"speed": "%{speed_download}"
}'
curl -w "$format" -o /dev/null -s "$1" | jq .
有次线上接口突然变慢,用这个脚本一测,发现是DNS解析时间异常。要不是有这个工具,可能还得多花好久才能定位到问题。
3. 批量文件下载
#!/bin/bash
# 并行下载脚本
download() {
local url=$1
local file=$(basename "$url")
curl -s -o "$file" "$url" && echo "Downloaded $file"
}
# 读取URL列表并行下载
cat urls.txt | xargs -P 5 -I {} bash -c 'download "{}"'
这个脚本有个有意思的地方:用xargs实现了并行下载。-P 5表示最多同时运行5个curl进程。
websocket支持
说到curl,可能很多人不知道它还支持websocket:
# 建立websocket连接
curl --include \
--no-buffer \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
--header "Sec-WebSocket-Version: 13" \
http://example.com/websocket
不过老实说,websocket测试我还是更喜欢用wscat这样的专门工具。
GraphQL查询
现在GraphQL越来越流行,curl也能轻松应对:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ user(id: \"123\") { name email } }"}' \
http://api.example.com/graphql
有个小技巧是把查询语句放在文件里:
curl -X POST \
-H "Content-Type: application/json" \
-d "@query.json" \
http://api.example.com/graphql
模拟移动设备
有时候需要测试移动端API,可以通过修改User-Agent来实现:
# 模拟iPhone
curl -A "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1" \
http://example.com
# 模拟Android
curl -A "Mozilla/5.0 (Linux; Android 10; SM-G960F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36" \
http://example.com
性能压测脚本
虽然说curl不是专门的压测工具,但简单测试还是可以的:
#!/bin/bash
# 简单的压测脚本
url=$1
requests=${2:-100}
concurrency=${3:-10}
tempfile=$(mktemp)
trap "rm -f $tempfile" EXIT
for i in $(seq 1 $requests); do
(
start=$(date +%s.%N)
http_code=$(curl -s -w "%{http_code}" -o /dev/null "$url")
end=$(date +%s.%N)
duration=$(echo "$end - $start" | bc)
echo "$http_code $duration"
) >> "$tempfile" &
# 控制并发数
if (( i % concurrency == 0 )); then
wait
fi
done
wait
# 统计结果
echo "Results:"
echo "Total requests: $requests"
echo "Concurrency: $concurrency"
echo "Status codes:"
awk '{print $1}' "$tempfile" | sort | uniq -c
echo "Timing stats (seconds):"
awk '{print $2}' "$tempfile" | \
awk '
BEGIN {min=999999; max=0}
{
sum+=$1;
if($1<min) min=$1;
if($1>max) max=$1;
values[NR]=$1
}
END {
avg=sum/NR;
if (NR%2) median=values[(NR+1)/2];
else median=(values[NR/2]+values[NR/2+1])/2;
print "Min: " min;
print "Max: " max;
print "Avg: " avg;
print "Median: " median
}'
自动化测试中的应用
在CI/CD流程中,curl也是个好帮手:
#!/bin/bash
# API自动化测试脚本
run_test() {
local name=$1
local url=$2
local expected=$3
echo "Running test: $name"
result=$(curl -s "$url")
if echo "$result" | jq -e "$expected" > /dev/null; then
echo "✅ Test passed"
return 0
else
echo "❌ Test failed"
echo "Expected: $expected"
echo "Got: $result"
return 1
fi
}
# 测试用例
run_test "Get user" \
"http://api.example.com/users/1" \
'.id == 1 and .name != null'
run_test "List users" \
"http://api.example.com/users" \
'length > 0'
curl的一些小技巧
说说一些我日常用的小技巧:
1. 格式化JSON输出
# 使用Python格式化
curl -s http://api.example.com | python -m json.tool
# 或者用jq(我更喜欢这个)
curl -s http://api.example.com | jq .
2. 测试网络连接
# 测试TCP连接
curl -v telnet://example.com:80
# 检查HTTPS证书
curl -vI https://example.com 2>&1 | grep "SSL certificate"
3. 上传大文件
# 显示进度条
curl -# -T bigfile.zip ftp://example.com/
# 断点续传
curl -C - -T bigfile.zip ftp://example.com/
一些有趣的应用
来分享几个有意思的用法:
1. 天气查询
curl wttr.in/beijing
2. IP地址查询
curl ip.gs
3. 获取公网IP
curl ifconfig.me
调试那些事
说实话,curl的调试功能是我最喜欢的部分。除了常用的-v参数,还有一些不太为人知的选项:
# 跟踪TCP包
curl --trace dump.txt http://example.com
# 只显示header
curl -s -D headers.txt http://example.com
# 显示TLS握手详情
curl --trace-ascii dump.txt https://example.com
写在最后
用了这么多年curl,最大的感受是:简单的工具,只要你用心琢磨,总能挖掘出更多可能性。curl就像是瑞士军刀,看起来普普通通,但总能在需要的时候帮你解决问题。
不过话说回来,工具终归是工具,关键还是要理解背后的原理。比如HTTP协议、TLS握手过程、各种认证机制等等。有了这些基础,你才能真正发挥出curl的威力。