# HTTP
# curl
:一个命令行工具,常用于访问 HTTP 服务器。
- 基于 libcurl 库开发,支持 HTTP、HTTPS、FTP、SMTP 等多种通信协议。
命令:
curl <URL>... # 访问指定网址(默认为 GET 方法),并将 HTTP 响应内容打印到 stdout
-X POST # --request ,使用指定类型的 HTTP 方法
-H "Connection: Keep-Alive" # --header ,加上 header(可以重复使用该命令选项)
-b "name=leo" # --cookie ,加上 cookies
-I # --head ,发送 HEAD 请求
-L # --location ,如果 HTTP 响应报文是重定向,则自动跟随
# 关于下载
-o <PATH> # --output ,将 URL 指向的资源保存为指定路径的文件
-O # 保存为当前目录下的同名文件
-C <offset> # --continue-at ,从 offset 处继续下载,offset 为 - 则会自动计算。这需要响应报文包含 Content-Range 字段,声明数据片段的起始、结束位置
# 关于身份认证
-k # --insecure ,不验证网站的 SSL 证书是否有效,但依然会建立 SSL 连接
-u USER[:PASSWORD] # 发送用户名,或者用户名加密码
# 发送 POST body 的选项
-d "id=001&name=leo" # --data ,在请求报文的 body 中,以纯文本形式发送数据。此时默认采用 POST 方法,并自动添加 HTTP 头部 "Content-Type : application/x-www-form-urlencoded"
--data-ascii "Hello" # 等价于 -d
--data-urlencode "Hello" # 经过 URLencode 之后再以纯文本形式发送
--data-binary "Hello" # 以二进制形式发送
--data-binary @f1 # 上述选项都可以通过 @filepath 的格式发送文件的内容。不过 --data-binary 是以二进制格式发送,避免乱码
-F key1=Hello # 发送 form 表单格式的 POST body ,此时默认采用 POST 方法,并自动添加 HTTP 头部 "Content-Type: multipart/form-data"
-F file1=@f1 # 该选项可以多次使用
-T f1 # 上传文件,此时默认采用 PUT 方法
# 关于通信协议
--ipv4 # 强制 curl 将目标域名解析到 ipv4 地址
--ipv6
--tlsv1.3 # 采用 TLS 1.3 协议
--http1.0 # 采用 HTTP/1.0 协议。默认优先采用 HTTP/1.1
--http2 # 采用 HTTP/2.0 协议,这需要 curl 7.43 以上版本
# 关于通信过程
-v # 显示通信过程的详细信息(包括 SSL握手过程、请求报文、响应报文)
--progress-bar # 显示进度条
-m 10 # --max-time,设置整个操作的超时时间(单位为秒)
--connect-timeout 3 # 与 Web 服务器建立 TCP 连接的超时时间(单位为秒)。默认会根据 net.ipv4.tcp_syn_retries 进行重试
--retry 0 # 如果建立 TCP 连接失败,或收到 HTTP 5xx 响应,则重试发出 HTTP 请求,最多重试 n 次。默认不会重试
# 使用代理
-x [PROTOCOL://][user:password@]HOST:PORT # --proxy
-x http://admin:[email protected]:80
-x socks5://10.0.0.1:1080
- 如果 URL 包含特殊字符,则要用单引号或双引号作为定界符,以免引发歧义。
- 使用 curl 时,默认不会显示进度表。
- 通过 -o 或 -O 选项下载文件时,会显示进度表。
- 将 stdout 从终端重定向到其它位置时,会通过 stderr 显示一个进度表。如下:
[root@CentOS ~]# curl 127.0.0.1 | grep ok % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 495 100 495 0 0 905k 0 --:--:-- --:--:-- --:--:-- 483k
- 可以改为显示一行简单的进度条:
[root@CentOS ~]# curl 127.0.0.1 --progress-bar > /dev/null ######################################################################## 100.0%
- 或者隐藏进度条,但这样可能隐藏其它报错信息:
curl 127.0.0.1 2> /dev/null
- 可以改为显示一行简单的进度条:
# 网络测试
虽然 curl 命令提供的 HTTP 客户端的功能少,不如浏览器。但使用 Linux 服务器时,经常要用 curl 命令下载文件,或进行网络测试。
- 执行
curl $ip:$port
,可测试本机能否向某个 ip 的某个 port 建立 TCP 连接。这里也可用 telnet 命令测试。 - 执行
curl cip.cc
,可查询本机使用的公网 IP 、地理位置。 - 执行
curl -v -X GET https://httpbin.org/get -H "accept: application/json"
,可测试本机发出的 HTTP headers 有哪些。
- 执行
假设需要测试主机 A 能否访问主机 B 的某个 TCP 端口,则可在主机 A 上执行命令
curl $ip:$port
。curl 命令在发送 HTTP 请求之前,会先向主机 B 发送 SYN=1 的 TCP 包,请求建立 TCP 连接。- 如果主机 B 的防火墙禁用了该端口,采用
iptables -j REJECT
方式拒绝通信,则会导致主机 A 报错:No route to host
- 如果主机 B 的防火墙放通了该端口,但没有进程在监听该 socket ,则会回复一个 RST 包,表示拒绝连接,导致主机 A 报错:
Connection refused
。例:[root@CentOS ~]# curl 127.0.0.1 curl: (7) Failed connect to 127.0.0.1:80; Connection refused
- 如果主机 A 长时间没有收到回复(连拒绝信息都没收到),则会在超时之后报错:
Connection timed out
。可能是以下原因:- 主机 A 与主机 B 的网络不连通。此时可进一步测试,通过 ping 命令尝试访问主机 B ,有两种结果:
- 能 ping 通主机 B ,说明网络连通,只是主机 B 的防火墙 drop 了发向该端口的 TCP 包。
- 不能 ping 通主机 B ,可能是以下原因:
- 的确网络不连通。
- 主机 B 的防火墙把 ICMP 协议也禁用了。
- 也可能是主机 B 的防火墙禁用了该端口,采用
iptables -j DROP
方式丢包。
- 主机 A 与主机 B 的网络不连通。此时可进一步测试,通过 ping 命令尝试访问主机 B ,有两种结果:
- 如果主机 B 的防火墙禁用了该端口,采用
当主机 A 与主机 B 成功建立 TCP 连接之后,主机 B 突然关闭 TCP 连接时:
- 如果主机 A 继续读取数据,主机 B 就会回复一个 RST 包,导致主机 A 报错:
Connection reset
- 如果主机 A 继续发送数据,主机 B 就会回复一个 RST 包,导致主机 A 报错:
Connection reset by peer
。例:[root@CentOS ~]# curl 127.0.0.1:22 SSH-2.0-OpenSSH_7.4 Protocol mismatch. curl: (56) Recv failure: Connection reset by peer
- 如果主机 A 继续读取数据,主机 B 就会回复一个 RST 包,导致主机 A 报错:
# wget
:一个命令行工具,与 curl 类型,只支持 HTTP、HTTPS、FTP 协议。
命令:
wget <URL>... # 访问指定网址(默认为 GET 方法),并将 HTTP 响应 body 保存为当前目录下的文件
-b # 在后台下载
-c # --continue ,如果要保存的文件已存在,则从该文件的长度之后继续下载(默认是保存为另一个文件,文件名加上递增的编号后缀)
-O f1.zip # 保存为指定路径的文件
-t 10 # 设置下载失败时的重试次数(0 是无限次)
--http-user=xxx # 发送用户名
--http-password=xxx # 发送密码
--limit-rate=300k # 限制下载速度
--no-check-certificate # 不检查 HTTPS 网址的证书
--spider # 不下载文件,可用于检测该网址是否有效
- 执行命令
wget <url>
,相当于执行curl -LO <url>
。 - 例:爬取网页
wget -e robots=off -r -np -p -k <url> -e robots=off # 忽略 robot 协议 -r # 递归下载该目录下的所有文件 -np # 递归下载时不遍历上层目录 -p # 下载显示在网页中的所有文件 -k # 将网页中的绝对链接改为本地链接