本文将介绍如何使用 curl 测试 HTTP(S) API。
cURL 是用于通过 URL 传输数据的命令行工具和类库,其功能非常强大,不仅可以完全地取代 Postman 之类的 GUI 工具,还提供很多高级功能。与他人协同排查问题时,只需要分享 curl 命令即可。
在开始介绍 curl 之前,先简单地介绍:
HTTP 请求报文的格式如下:
xxxxxxxxxx
请求行CRLF
请求头CRLF
...
请求头CRLF
CRLF
请求体
其中 CRLF 代表回车(Carriage-Return,即 '\r')换行(Line-Feed,即 '\n')。
请求行由使用空格分隔的三部分组成:
请求头由使用冒号分隔的名称和值组成,比如:
xxxxxxxxxx
User-Agent: curl/7.59.0
下图是 HTTP 请求报文的示例:
注1:图片来自 https://www.cnblogs.com/lmh001/p/9928517.html
注2:上面是未开启 Keep Alive 的请求流程
下面我们将看到 curl 支持定制 HTTP 请求中的任意部分,也支持定制请求流程中的步骤。
-X
用于指定请求方法比如:
xxxxxxxxxx
curl -X POST -d '{"key": "value"}' -H 'Content-Type: application/json' http://127.0.0.1:9090/post
-0
表示使用 HTTP 1.0(curl 默认使用 HTTP 1.1)比如:
xxxxxxxxxx
curl -0 http://127.0.0.1:9090/get
curl 通过 --dns-servers
选项,指定将要使用的 DNS 服务器的地址。其值的格式是:
xxxxxxxxxx
host[:port][,host[:port]]...
curl 通过 --connect-to
选项,指定将要连接的主机和端口(代替 URL 中的主机和端口)。其值的格式是:
xxxxxxxxxx
HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT
其中 HOST 是请求中的主机,PORT 是请求中的端口,CONNECT-TO-HOST 是将要连接的主机,CONNECT-TO-PORT 是将要连接的端口。
注意,“connect to” 中的主机和端口只用于建立网络连接,不影响用于 SSL/TLS 和应用层协议的主机和端口。
curl 通过 --resolve
选项,自定义主机名到 IP 地址的解析。其值的格式是:
xxxxxxxxxx
HOST:PORT:ADDRESS[,ADDRESS]...
其中 HOST 是 curl 尝试解析的主机名,PORT 是 curl 将要连接的 HOST 上的服务端口号,ADDRESS 是一或多个 IP 地址。
该选项使用用于 HOST+PORT 对的条目预先填充 DNS 缓存,因此针对 HOST+PORT 的各种操作都将使用 ADDRESS 代替。比如:
xxxxxxxxxx
curl --resolve "test.domain:9090:127.0.0.1" http://test.domain:9090/get
--limit-rate
用于限制传输速度,模拟慢速网络比如:
xxxxxxxxxx
curl --limit-rate 1K http://127.0.0.1:9090/get
上面的命令将传输速度限制为每秒 1KB。
curl 通过 -b
、--cookie
选项,向服务端发送 Cookie。比如:
xxxxxxxxxx
curl -b 'key1=value1' http://127.0.0.1:9090/cookie
上面的命令将生成请求头 Cookie: key1=value1
,向服务端发送一个名称为 key1,值为 value1 的 Cookie。
xxxxxxxxxx
curl -b 'key1=value1;key2=value2' http://127.0.0.1:9090/cookie
上面的命令将向服务端发送 2 个 Cookie。
xxxxxxxxxx
curl -b cookies.txt http://127.0.0.1:9090/cookie
上面的命令从本地文件 cookies.txt 中读取 Cookie,然后将其发送到服务端。
curl 通过 -c
、--cookie-jar
选项,在操作完成后,将 Cookie 写到文件中。比如:
xxxxxxxxxx
curl -c cookies.txt http://127.0.0.1:9090/cookie
Cookie 文件的内容类似:
xxxxxxxxxx
# Netscape HTTP Cookie File
# http://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
127.0.0.1 FALSE / FALSE 1609147946 key1 value1
127.0.0.1 FALSE / FALSE 1609147946 key2 value2
-A
用于指定 User Agent比如:
xxxxxxxxxx
curl -A 'Custom User Agent' http://127.0.0.1:9090/user-agent
-H
、--header
用于自定义请求头比如:
xxxxxxxxxx
curl -X POST -d '{"key": "value"}' -H 'Content-Type: application/json' -H 'X-Request-Id: id-123' http://127.0.0.1:9090/custom-headers
curl 通过 -d
、--data
选项,向服务端 POST 数据。比如:
xxxxxxxxxx
curl -d 'post data' http://127.0.0.1:9090/post
curl 通过 --data-urlencode
选项向服务端 POST URL 编码的数据。比如:
xxxxxxxxxx
curl --data-urlencode 'post data' http://127.0.0.1:9090/post
-d
、--data
和 --data-urlencode
选项的值也可以是 “@” + 本地文件名。比如:
xxxxxxxxxx
curl -d @post.dat http://127.0.0.1:9090/post
上面的命令读取本地文件 post.dat 的内容,然后将其发送到服务端。
-d
、--data
和 --data-urlencode
还可以与 -G
、--get
选项结合使用。比如:
curl -G --data-urlencode @post.dat http://127.0.0.1:9090/get
上面的命令读取本地文件 post.dat 的内容,自动地对其进行 URL 编码,然后使用 GET 请求将数据发送到服务端。
curl 通过 -T
、--upload-file
选项,向服务端上传文件。比如:
xxxxxxxxxx
curl --upload-file put.dat http://127.0.0.1:9090/put
上面的命令将向服务端发送一个 PUT 请求,请求体是本地文件 put.dat 的内容。
curl 通过 -F
、--form
选项,使用 multipart 的方式向服务端传输数据。比如:
xxxxxxxxxx
curl --form 'file=@multipart.dat' http://127.0.0.1:9090/multipart
上面的命令将添加请求头 Content-Type: multipart/form-data; boundary=<boundary string>
,然后将本地文件 multipart.dat 作为 file 字段上传。
-F
、--form
选项还支持指定 MIME 和文件名,比如:
xxxxxxxxxx
curl --form 'file=@multipart.dat;type=text/plain;filename=test.txt' http://127.0.0.1:9090/multipart
-i
用于在输出中包含协议头比如:
xxxxxxxxxx
curl -i http://127.0.0.1:9090/get
上面的命令在收到服务端的响应后,首先输出响应头,然后输出空行,最后输出响应体。
-I
、--head
用于向服务端发送 HEAD 请求比如:
xxxxxxxxxx
curl -I http://127.0.0.1:9090/head
curl 默认不跟进重定向,可以通过指定 -L
、--location
选项,使 curl 跟进重定向。比如:
xxxxxxxxxx
curl -L http://127.0.0.1:9090/redirect
当指定 -L
、--location
选项时,可以通过 --max-redirs
选项指定最大跟进次数。比如:
xxxxxxxxxx
curl -L --max-redirs 100 http://127.0.0.1:9090/infinitely-redirect
当达到最大跟进次数时,curl 将抛出类似下面的错误:
xxxxxxxxxx
curl: (47) Maximum (100) redirects followed
curl 通过 -x
、--proxy
选项,指定将要使用的代理服务器的地址,其值的格式是:
xxxxxxxxxx
[protocol://]host[:port]
curl 通过 -U
、--proxy-user
选项,指定代理服务器的账号和密码,其值的格式是:
xxxxxxxxxx
user:password
-u
、--user
用于指定服务端的账号和密码比如:
xxxxxxxxxx
curl -i -u 'user:password' http://127.0.0.1:9090/basic-auth
上面的命令将添加请求头 Authorization: Basic dXNlcjpwYXNzd29yZA==
-v
、--verbose
用于调试curl 将输出通信的整个过程。比如:
xxxxxxxxxx
curl -v http://127.0.0.1:9090/verbose
-o
、--output
用于将输出写到指定的文件(而非标准输出)比如:
curl -o /dev/null http://127.0.0.1:9090/get
-O
、--remote-name
用于将输出写到文件将 URL 的最后一部分当作文件名,比如:
xxxxxxxxxx
curl -O http://127.0.0.1:9090/get
-s
和 -S
选项-s
选项用于开启静默模式,curl 将不输出任何信息;-S
选项和 -s
选项一起使用,使 curl 在发生错误时,输出错误信息。比如:
xxxxxxxxxx
curl -sS http://127.0.0.1:9090/get
-w
选项curl 的 -w
选项用于在一次完整且成功的操作后,向标准输出输出指定格式的内容。输出内容由普通字符串和变量组成,输出变量的格式是 %{variable_name}
。curl 用合适的值替代输出内容中的变量,可用变量如下:
比如:
xxxxxxxxxx
curl -w 'url effective: %{url_effective}\nhttp code:%{http_code}\ntime total:%{time_total}\ntime namelookup: %{time_namelookup}\ntime connect: %{time_connect}\ntime appconnect: %{time_appconnect}\ntime pretransfer:%{time_pretransfer}\ntime redirect: %{time_redirect}\ntime starttransfer: %{time_starttransfer}\n' -Sso /dev/null http://127.0.0.1:9090/get
--connect-timeout
选项用于指定建立连接的超时时间,单位是秒。比如:
xxxxxxxxxx
curl --connect-timeout 1 http://127.0.0.1:9090/get
-m
、--max-time
选项用于指定最长传输时间,单位是秒。比如:
xxxxxxxxxx
curl -m 2 http://127.0.0.1:9090/sleep/1
当传输时间达到该限制时,如果传输仍然没有结束,那么 curl 将以类似下面的错误退出:
xxxxxxxxxx
curl: (28) Operation timed out after 2001 milliseconds with 34 out of -1 bytes received
-1
、--tlsv1
:使用 TLSv1.0 或更高版本--tlsv1.0
:使用 TLSv1.0--tlsv1.1
:使用 TLSv1.1--tlsv1.2
:使用 TLSv1.2--tlsv1.3
:使用 TLSv1.3--cacert <file>
:用于验证对端的 CA 证书--cert <certificate[:password]>
:客户端证书文件和密码--cert-type <type>
:证书文件类型(DER/PEM/ENG)--key <key>
:私钥文件名--key-type <type>
:私钥文件类型(DER/PEM/ENG)-k
、--insecure
:当使用 SSL 时,允许非安全的服务端连接