《cURL 必知必会》阅读摘要记录
- 陈大剩
- 2025-05-17 21:51:24
- 31
书籍简介
作者: [美] DanielStenberg(丹尼尔·斯坦伯格)
译者:薛命灯
出版年: 2020-01-01
页数: 147
定价: 59.00 元
装帧:平装
ISBN: 9787115523860
第 1 章 cURL项目
开源项目比较有趣的一点是,它们通常被称为“项目”,好像它们在某种程度上也会受到时间的限制或者永远无法完成一样。cURL“项目”团队实际上是由一些致力于软件开发的个人志愿者组成的,他们肩负着共同的使命:使用网络协议进行可靠的数据传输,并提供任何人都可以使用的免费代码。
1.1 它是如何开始的
为了让汇率尽可能准确,机器人每天从汇率网站下载汇率数据。要想完成这个任务,需要使用一个小工具通过 HTTP
下载数据。当时,找到了一款名为 HttpGet 的小工具(由巴西人Rafael Sagula开发)。这个工具可以用于下载数据,只是需要做一些调整。很快就接管了这个工具几百行代码的维护任务。
1998 年 3 月 20 日才是 cURL 的生日。(在 HttpGet 上改版而来)
1.2 命名问题
这个工具用于上传和下载 URL 指定的数据。它会显示数据(默认情况下),用户可以看到(see)URL,并且see可以简写为单个字母c。此外,它是一个客户端程序,一个URL客户端,字母c也可以表示客户端(client),因此就有了cURL这个名字。
大多数人用 k 作为 cURL 的开头音,就像英语单词 curl 那样。它与 girl 和 earl 很押韵。
1.3 curl 可以做什么
cURL 项目的主要目的和侧重点围绕着两个产品展开:
- 命令行工具 curl;
- 提供C API的 libcurl 库;
这个工具和库都基于网络协议,为指定的 URL 资源执行网络传输。
libcurl 是用传统的C语言开发的,不过也有使用其他语言开发的版本,人们为其他语言创建了相应的libcurl绑定。
libcurl 库可以用于各种需要网络传输的嵌入式设备:车载信息娱乐系统、电视机、蓝光播放器、机顶盒、打印机、路由器、游戏系统等
1.3.1 命令行工具 curl
curl 通过命令行运行,可以将数据输出到 stdout(终端)的工具,奉行 “一切皆管道”,curl 也支持多个 url。
1.3.2 libcurl 库
2000年,curl 的核心引擎被抽离成一个库,同年8月,libcurl7.1发布,其中包含了所有沿用至今的概念。从那时起,curl就成了一个基于libcurl 构建命令行工具的逻辑层,想要在软件、平台、架构中添加客户端文件传输功能的人都可以使用 libcurl,这也是 libcurl 的设计目标。
1.4 开发团队
一些贡献者的名称。
1.5 curl 的用户
curl 有十亿用户,但是并不是一个切确的数字,因为利用趋势进行的估算和猜测。curl 是开源的,任何人都可以重新发行源代码或二进制文件。下载量并不能准确的反应实际的数字。
用于 PHP 的 libcurl 绑定是 libcurl 的第一批真正得到了广泛应用的绑定之一。它很快就成了 PHP 用户传输数据的默认方式,由于这样的状态保持了十多年,PHP 已经被证明是互联网领域相当流行的技术(最近的数据显示,大概四分之一的网站都在使用 PHP)。
一些流量很大的站点也在使用PHP,并在后端使用了 libcurl,比如 Facebook 和 雅虎。
第 2 章 命令行基础
curl 是一个可执行的二进制文件,但 cURL 项目本身不提供二进制文件。curl 的二进制文件需要根据不同的操作系统进行构建,而且通常受不同版本系统的约束。
2.1 命令行选项
在使用 curl 时,可以使用零到多个命令行选项以及你想要访问的 URL 或 URL 集合来调用它。curl 支持 200 多个不同的选项。
2.1.1 短选项
命令行选项可以将 curl 执行的任务信息传给 curl ,如 -v 选项让 curl 切换到详细(verbose)模式。
curl -v http://ipinfo.io
-v 是一种 “短选项”,即一个减号后面跟着一个字母。很多选项属于切换开关,用于启动或切换两个已知状态,如:
curl -vL http://ipinfo.io
curl 命令会解析整行命令,可以将 “短选项” 放在任意位置,也可以单独指定短选项,如:
curl -v http://ipinfo.io -L
2.1.2 长选项
短选项使用起来非常方便,但因为字母的数量有限,需要用到的选项又比较多,所以并非所有选项都可以使用单个字母来表示,于是就有了长选项。
另外,为了方便,也为了让脚本更易于阅读,大多数短选项都有对应的长选项别名。
长选项使用两个减号(或者称为破折号),后面跟上选项名,而且每两个减号后面只能跟一个选项名。使用长选项打开详细模式,如:
curl --verbose http://ipinfo.io
2.1.3 选项参数
并非所有选项都只用于启用或禁用某项功能。对于一些选项,需要向它们传递一些数据, 如用户名或文件路径。需要先指定选项,然后给出参数,中间用空格分隔。例如,可以通过 HTTP POST
将一个字符串发送给服务器。
curl -d arbitrary http://example.com
也可以使用长选项
curl -data arbitrary http://example.com
实际上,如果使用带参数的短选项,可以不使用空格进行分隔。
curl -darbitrary http://example.com
2.1.4 带空格的参数
有时向选项传递参数中包含了一个或多个空格。例如,将 user-agent 字段设置为 I am your father,包括当中的三个空格。此时你需要给字符串加上引号。
curl -A " I am your father" http://example.com
如果字符串本身包含了双引号,比如想要向服务器发送JSON字符串(这种情况很常见),需要使用单引号(但在Windows系统上使用单引号可能不行)。如:
curl -d '{"name": "Darth" }' http://example.com
想要避免使用单引号,则可以通过文件将数据传给 curl,这样就无须使用额外的引用。假设 json 文件包含了上述数据:
curl -d @json http://example.com
2.1.5 负选项
对于开关选项,既可以用它们打开某些功能,也可以通过它们关闭功能。你也可以使用长选项,在选项名前面加上 “no-” 前缀。例如,关闭详细模式。
curl --no-verbose http://ipinfo.io
2.2 不同版本的选项
curl 每八周就会发布一个新版本,因此不可避免的是,并不总能使用到最新版的 curl。有时使用的可能是几年前的版本。curl 的开发人员努力不去改变已有行为。1998年、2003年或2010年编写的命令行都可以不经修改直接使用现今的 curl 来运行。
2.3 URL
之所以称为 curl,是因为 curl 的名字中包含了 URL(Uniform Resource Locator,统一资源定位符)。URL 就是 curl 的操作对象。URL就是通常使用的网址字符串,如经常看到的以 http:// 为前缀或以 www 开头的网址。
严格来说,URL 是之前使用的名称,URI(Uniform Resource Identifier,统一资源标识符)才是更现代、更正确的叫法。RFC3986给出了它们的语法定义。curl 接受 “URL” 作为输入,但实际上是 “URI”。curl 支持的大多数协议也有相应的 URI 语法文档,这些文档描述了这些 URI 格式的工作原理。
2.3.1 scheme
URL 以 “scheme” 作为开头,scheme 是 “http:// ” 这部分内容的官方名称,用于告诉 curl 传入的 URL 使用了哪个协议。scheme 必须受当前 curl 版本支持,否则 curl 将显示错误消息并退出。
书中 Endpoint 其实和 URL 类似。
2.3.2 scheme 分隔符
“://” 将 scheme 标识符与 URL 的其余部分分开,可以支持如下写法:
file://localhost/path/to/file
file://127.0.0.1/path/to/file
file:///path/to/file # Windows
2.3.3 不使用 scheme
curl 可以允许用户省略 URL 的 scheme 部分,curl 会根据主机名的第一部分猜测要使用哪种协议。没有提供 scheme 的其他 URL 将默认使用HTTP。
可以通过–proto-default 选项将默认协议修改为 HTTP 以外的其他协议。
2.3.4 用户和密码
scheme 后面可以跟用户名和密码。例如,使用给定的用户名和密码列出FTP服务器目录中的内容:
curl ftp://user:password@example.com/
现在通常不建议使用这种语法,因为这样很容易在脚本或其他地方泄露这些信息。
2.3.5 主机名或地址
可以使用 IPv4 或 IPv6 地址。
curl http://127.0.0.1/
curl http://[::1]/
2.3.6 端口号
每个协议默认都有一个“端口号”,除非指定特定端口号(:xxx 冒号)。
curl http://127.0.0.1:8080/
2.3.7 路径
每个 URL 都包含一个路径,没有指定,则使用 “/”,如 readme 是路径。
curl http://127.0.0.1:8080/readme
路径的用法取决于具体的协议,对于具有目录概念的协议,可以在 URL 尾部以一个斜杠表示它是目录,而不是文件。因此,请求 FTP服务器的目录列表时需要使用斜杠。
2.3.8 FTP 类型
可以标识 FTP 服务器文件的 URL 提供了一个特性来告诉客户端(这里是curl)资源的文件类型。是因为FTP可以改变传输模式,在不同的模式下使用不同的处理方式。
curl "ftp://example.com/foo;type=A" #;type=A 告诉 curl 当前使用的是 ASCII 类型
curl "ftp://example.com/foo;type=I" #;type=I 为二进制,默认为二进制
curl "ftp://example.com/foo;type=D" #;type=D 为目录
2.3.9 片段
其实就是注释,用 “#” 来做注释,并且不会发送出去。
curl ipinfo.io #这是一个注释
2.3.10 浏览器的“地址栏
现代 Web 浏览器的 “地址栏” 中一般使用的不是 URL 或 URI。有时在浏览器地址栏中看到的内容与传给curl的内容存在很大差别,实际上,它们主要使用 IRI 也就是 URI 的超集,以支持国际化(如支持非拉丁符号)。它们还会处理空格、编码地址等,但规范中并没有说明这些事情应该由客户端完成。
2.3.11 多个选项和多个 URL
curl 支持数百个 命令行选项 和 无限数量 的 URL。如果 shell 或命令行系统能够支持,那么传给 curl 的命令行长度实际上是没有限制的。
curl 首先会解析整个命令行,应用给定的命令行选项,然后(按从左到右的顺序)遍历URL 并执行相应操作。
curl 会在处理完最后一个URL后返回一个退出码。想让 curl 在第一次出现错误时就退出, 则可以使用 –fail-early 选项。
2.3.12 URL 的单独选项
curl 还提供了另一个选项(–next,短格式为 -;),用于在一组选项和 URL 之间插入间隔。 当命令行解析器遇到 –next 选项时,它会将后面的选项应用于下一组 URL 。因此,–next 选项其实是一组选项和URL之间的分隔符。
curl ipinfo.io --next www.baidu.com
2.3.13 连接重用
在高带宽的网络中,建立TCP连接(尤其是TLS连接)是一个缓慢的过程。curl 在内部维护着一个连接池,这可以让之前使用过的连接继续存活一段时间,因此后续发给相同主机的请求可以重用这些已经建立的连接。
连接池中的连接可以在 curl 运行期间保持活跃状态,但最好还是在同一个命令行中完成多次传输,而不是单独运行多个 curl 命令行。
2.4 URL通配
curl 提供了“通配”(globbing)的方式来指定这类URL。使用 []
或 {}
进行通配,也可以使用 -g 或 –globoff 禁用它。
curl 通配功能不是基于 libcurl 库提供的。
2.4.1 数值范围
可以使用 [N-M] 语法来指定一个数值范围,其中N是起始索引,M是结束索引(包括M在内)。
例如:
# 请求100个以数字命名的图像
curl -o http://example/[1-100].png
curl -o http://example/[001-100].png
curl -o http://example/[1-100:2].png #步进为2
2.4.2 字母范围
curl 可以处理字母范围,例如:
curl -o http://example.com/section[a-z].html
2.4.3 列表
可以使用列表范围进行通配,例如:
curl -o http://example.com/{one,two,three}.html
2.4.4 组合
可以在同一个 curl 中使用多个通配,例如:
curl -o http://example.com/[a-z]-{one,two,three}.html
2.4.5 输出变量
URL 中的每个通配都对应一个单独的变量,可以通过 “#[num” 来引用,即在 “#” 后面跟上与通配对应的数字,从 1(对应第一个通配)开始,以最后一个通配结束。
例如,保存两个不同网站的主页:
curl http://{one, two}.example.com -o "file_#1.txt"
2.5 列出所有的命令行选项
curl 有 200 多个命令行选项,而且更多选项正在不断被添加进来。选项的数量可能在未来几年内达到 250 个。
curl --heIp
或 curl-h
将列出所有选项,并提供简要的说明。不够详细的话,可以使用 --help all
或 curl --manual
展示全部文档。
2.6 配置文件
curl 命令行选项的数量很容易膨胀,变得难以维护,可以使用 -K
或 --config
“配置文件功能”,允许将命令行参数写到文本文件中,然后告诉 curl。
curl -K cmdline.txt it927.com
cmdline.txt 文件如下:
# 这个是注释(可以使用空格),使用 -I、-v 等模式,长选项可以不使用 ”--“,选项参数可以使用 ”=“ 或 ”:“
-I
-v
location
user-agent = "xxx"
如果想在配置文件中指定 URL,则必须使用–ur1或 url,否则无法解析,例如:
url = "it927.com" --url it927.com
2.7 密码和窥探
密码是敏感信息,泄露密码可能会令其他人也能访问到受保护的资源和数据。
curl 提供了几种方式来接收用户的密码,-u 或 –user,如:
curl -u dasheng:123456 http://www.it927.com
2.7.1 命令行密码泄露
在命令行输入了密码,而命令行可能对同一系统上的其他用户是可见的,curl 会尝试从进程列表中清空密码来降低密码泄露风险。
也可以使用 -u 选项,但是不指定密码,curl 会在运行时提示用户输入密码,另一种方案是使用 .netrc 文件或配置文件。
2.7.2 网络泄露
curl 使用 HTTP 传输会存在 中间人 或 其他窥探者 窥探连接,并查看发送的内容。可以使用 HTTPS 或 FTPS 这类协议,如果一定要使用普通文本和不安全协议,可以看看是否不以明文形式发送凭证和身份验证方法。如果使用的是 HTTP,可以尝试 Digest(–digest)、Negotiate(–negotiate)和 NTLM(–ntlm)
2.8 进度显示器
curl 有一个内置的进度指示器。当调用 curl 来传输数据(上传或下载)时,它可以在终端上显示传输的进度,比如当前的传输速率、已经用掉的时间以及还需要多长时间才能完成传输。在终端输出的时候默认会禁用,用户可以通过 -s 或 –silent 强制关闭。
可以使用 -# 或 –progress-bar 使用简单的下载进度指示器。
第 3 章 使用 curl
curl 支持或可以支持(需要进行构建)以下这些协议:
DICT、FILE、FTP、FTPS、GOPHER、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、SFTP、SMB、SMTP、SMTPS、TELNET 和 TFTP。
3.1 详细模式
如果 curl 命令没有执行或返回所期望的东西,你的第一直觉反应应该是使用 -v 或 --verbose
选项来运行命令,以便获取更多详细信息。
curl -v it927.com -I
* Host it927.com:80 was resolved.
* IPv6: (none)
* IPv4: 43.136.107.225
* Trying 43.136.107.225:80...
* Connected to it927.com (43.136.107.225) port 80
> HEAD / HTTP/1.1
> Host: it927.com
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 301 Moved Permanently
HTTP/1.1 301 Moved Permanently
< Server: nginx
Server: nginx
< Date: Sat, 15 Feb 2025 16:06:53 GMT
Date: Sat, 15 Feb 2025 16:06:53 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 162
Content-Length: 162
< Connection: keep-alive
Connection: keep-alive
< Location: https://it927.com/
Location: https://it927.com/
< Strict-Transport-Security: max-age=31536000
Strict-Transport-Security: max-age=31536000
<
* Connection #0 to host it927.com left intact
3.1.1 –trace 和 –trace-ascii
有时只使用 -v 是不够的,特别是当想要保存包括实际传输数据在内的完整消息时。可以使用 --trace
和 --trace-ascii
选项
--trace [filename]
选项可以将完整的跟踪的信息保存到指定文件中,也可以使用 -
代替文件名,将内容打印到 stdout 。
curl --trace dump https://www.it927.com
curl --trace-ascii - https://www.it927.com
--trace [filename]
默认为十六进制 ,如果不想用十六进制,则用 --trace-ascii [filename]
则打印。
3.1.2 –trace-time
如果使用了这个选项,则所有的输出信息前面都会被加上高精度的时间戳。它可以与常规的 -v 和 –verbose 选项以及 –trace 和 –trace-ascii 选项一起使用,如下所示:
curl --trace-time -v https://www.it927.com -I
00:42:17.427841 * Host www.it927.com:443 was resolved.
00:42:17.428141 * IPv6: (none)
00:42:17.428157 * IPv4: 112.3.31.131
00:42:17.428200 * Trying 112.3.31.131:443...
00:42:17.460407 * Connected to www.it927.com (112.3.31.131) port 443
00:42:17.460498 * ALPN: curl offers h2,http/1.1
00:42:17.460812 * (304) (OUT), TLS handshake, Client hello (1):
00:42:17.466523 * CAfile: /etc/ssl/cert.pem
00:42:17.466549 * CApath: none
00:42:17.595381 * (304) (IN), TLS handshake, Server hello (2):
00:42:17.595774 * (304) (IN), TLS handshake, Unknown (8):
00:42:17.595858 * (304) (IN), TLS handshake, Certificate (11):
00:42:17.597703 * (304) (IN), TLS handshake, CERT verify (15):
00:42:17.597815 * (304) (IN), TLS handshake, Finished (20):
00:42:17.598053 * (304) (OUT), TLS handshake, Finished (20):
00:42:17.598089 * SSL connection using TLSv1.3 / AEAD-AES256-GCM-SHA384 / [blank] / UNDEF
00:42:17.598113 * ALPN: server accepted h2
00:42:17.598135 * Server certificate:
00:42:17.598166 * subject: CN=www.it927.com
00:42:17.598194 * start date: Dec 19 06:58:42 2024 GMT
00:42:17.598213 * expire date: Mar 19 06:58:41 2025 GMT
00:42:17.598242 * subjectAltName: host "www.it927.com" matched cert's "www.it927.com"
00:42:17.598265 * issuer: C=US; O=Let's Encrypt; CN=R11
00:42:17.598285 * SSL certificate verify ok.
00:42:17.598434 * using HTTP/2
00:42:17.598524 * [HTTP/2] [1] OPENED stream for https://www.it927.com/
00:42:17.598548 * [HTTP/2] [1] [:method: HEAD]
00:42:17.598566 * [HTTP/2] [1] [:scheme: https]
00:42:17.598584 * [HTTP/2] [1] [:authority: www.it927.com]
00:42:17.598601 * [HTTP/2] [1] [:path: /]
00:42:17.598619 * [HTTP/2] [1] [user-agent: curl/8.7.1]
00:42:17.598636 * [HTTP/2] [1] [accept: */*]
00:42:17.598703 > HEAD / HTTP/2
00:42:17.598703 > Host: www.it927.com
00:42:17.598703 > User-Agent: curl/8.7.1
00:42:17.598703 > Accept: */*
00:42:17.598703 >
这些都是本地时间,格式为 小时:分钟:秒,然后是微秒。
3.1.3 HTTP/2
在使用 HTTP/2 进行文件传输时,curl 将发送和接收被压缩的标头信息。因此,为了以可读和可理解的方式显示传出和传入的 HTTP/2 标头信息,curl 将显示未经压缩的版本,就像它们在 HTTP/1.1 版本中显示的那样。
3.1.4 –write-out
--write-out
这个选项经常被人们忽略,但它是 curl 命令行选项当中的一颗小瑰宝。–write-out(-w) 会在传输任务完成后打印一些信息,并且它还提供了大量可添加到输出内容中的变量,这些变量包含了与传输相关的信息。
如果将一个字符串传给这个选项,那么这个字符串就会被打印出来:
curl -w "who are you?" baidu.com
如果在字符串前面加上‘@‘,那么cul就会从指定文件中读取字符串:
curl -w @filename baidu.com
如果使用 -
作为文件名,那么 curl 就会从标准输人(stdin)读取字符串:
curl -w @- www.baidu.com
"响应状态码: %{http_code}\n总耗时: %{time_total} 秒\n"
按下回车键后,curl
不会立即发起对 www.baidu.com
的请求,而是等待你从标准输入提供自定义输出格式。然后再按 Ctrl + D
(在 Windows 上是 Ctrl + Z
)来结束输入并发起请求.
--write-out
可以输出从 HTTP 传输的 Content–Type 和 响应码,使用新行和一些额外的文本进行分隔:
curl -w "响应状态码: %{http_code}\n总耗时: %{time_total} 秒\n" www.baidu.com
3.1.5 可用的 –write-out 选项
可用的 –write-out 选项太多无法写出,可参考:–write-out 选项
3.1.6 静默模式
与详细模式相反的是静默模式。-s(–silent)选项可以让 curl 关闭进度指示器,而且不会在发生错误时输出任何错误信息。它变得无声无息,但仍然会输出你请求下载的数据。
启用静默模式后,你可以通过添加 -s
或 --show-error
来要求它在发生错误时输出错误信息。
3.2 持久连接
在建立 TCP 连接时,curl 将保留旧连接一段时间,如果下一次要连接到同一主机,那么就可以重用相同的连接,从而节省大量时间。我们称之为持久连接。curl 将始终尝试保留连接,并尽可能重用现有连接。
3.3 下载
“下载” 的意思是从网络服务器获取数据,将数据从服务器下载到运行 curl 的计算机上。下载可能是 curl 最常见的使用场景一获取URL指定的特定数据到你的机器上。
3.3.1 究竟下载了哪些内容
可以通过 URL 来指定 curl 需要下载哪些资源。除非另有说明,否则 curl 默认下载 URL 定的资源。
在以下示例中,要下载的 URL 是 “http://www.it927.com/”:
curl http://www.it927.com
如果在命令中指定了多个 URL,那么 curl 将一个一个下载所有的 URL,在一个传输完成之前,它不会启动下一个传输。
3.3.2 保存下载的内容
curl 会将下载的数据输出到 stdout,除非你明确告诉它使用其他的处理方式。如果想要将下载的数据传给另一个程序,则可以将数据输出到 stdout,但这并不是处理下载内容的最佳方式。
可以通过 -o [filename]
(–output)为选项指定一个特定文件名保存下载的内容,filename 可以是文件名,也可以是文件的相对路径或完整路径。
curl -o output.html www.it927.com
curl -o /tmp/index.html www.it927.com
3.3.3 用 URL 指定的文件名保存内存
很多 URL 的最右边部分已经包含了文件名,可以用 -O(大写o)保将其作为目标文件名。
这里默认将保存为 index.php 文件
curl -O https://www.php.net/manual/zh/index.php
3.3.4 从服务器获取目录文件名
HTTP 服务器可以选择在响应消息中提供 Content-Disposition
标头。这个标头可能包含服务器建议的文件名,可以让 curl 使用这个名字作为本地文件名。-J (–remote-header-name) 选项就是用来打开这个功能的。如果同时还使用了 -O 选项,那么 curl 默认使用 URL 中的文件名, 并且只有当响应消息中包含有效的 Content-Disposition
标头时,它才会使用这个建议的文件名。
-J 选项注意事项:
- 只会使用文件最右边部分,服务器目录会被忽略;
- 文件名是服务器提供,可能会覆盖本地同名文件;
- 文件名编码和字符集问题,可能会得到一个 URL 编码的文件名;
3.3.5 HTML 和字符集
HTML 页面可能会使用某个指定的字符集,如果和本地编辑器字符集不一样,会导致乱码,可以用 iconv 将文件转换为不同的字符集。
3.3.6 压缩
curl 可以要求 HTTP 和 HTTPS 服务器提供压缩过的数据,并在收到数据自动进行解压,在带宽比 CPU 更紧缺的情况下,可以缩短时间收到更多的数据。
HTTP压缩可以通过两种机制来实现,一种被认为是“正确的方式”,另一种在实际中使用得更为广泛!压缩 HTTP 内容的常用方法是使用Content-Encoding 标头。你可以使用 --compressed
选项:
curl --compressed https://www.it927.com
启用这个选项后,如果服务器支持压缩,它会传输压缩过的数据,curl 会在保存或发送到 stdout 前对数据进行解压。除了可能会注意到传输变得更快之外,用户并不会真正看到或感觉到压缩过程。
–compressed 请求服务器使用一种受支持的压缩算法来压缩数据。Transfer-Encoding 是种比较罕见的方法,它是为自动压缩和解压而创建的一个标头,但并没有被广泛采用。你可以通过 –try-encoding 选项让 curl 向服务器请求 Transfer-Encoding 压缩:
curl --try-encoding https://www.it927.com
3.3.7 shell 重定向
在 shell 或其他命令行系统中调用curl时,这些环境通常会为你提供输出重定向能力。
在大多数 Linux、Unix shell 以及 Windows 命令提示符中,你可以使用 >filename 将 stdout 重定向到文件中。
curl www.it927.com > filename
这个时侯候再使用 -o或 -O 选项就会变得多余。
3.3.8 多个下载
可以在命令中进行多个 URL 下载,可以下载保存自定义名字的本地文件,但是每个 URL 必须要存储指令,否则会输出到 stdout。
curl -o one.html www.baidu.com
curl -O -O www.baidu.com/a.txt https://www.php.net/manual/zh/index.php
注意:-o 用于单个下载,-O 可以用多个,每个 URL 必须要存储指令,否则会输出到 stdout。
3.3.9 让所有 URL 使用自己的文件名
为了避免在 多个下载 一百个 URL 时添加一百个 -O 选项,可以引入了--remote-name-all
选项。
这让 -O 成为所有给定 URL 的默认操作方式。仍然可以为 URL 提供单独的 “存储指令”,但对于没有提供单独 “存储指令” 的 URL,则默认使用 -O 选项,而不是输出到 stdout。
3.3.10 “浏览器显示的是其他内容”
curl 的一个常见使用场景是像浏览器那样获取 URL,但浏览器做的事情比 curl 要多得多,curl 在终端输出的内容可能与你在浏览器窗口中看到的内容完全不一样。
3.3.11 客户端差异
curl 只会获取你要求它获取的内容,不会解析获取到的内容,所以动态的 JS 和 CSS 不会显示,也不请求其他文件。
3.3.12 服务端差异
服务端差异取决于客户端类型,curl 要向浏览器那样相同的响应非常困难,可能会有验证环节,curl 无法通过。
3.3.13 中介欺骗
中介就是代理,可能是显式的,也可能是隐式的。某些环境会强制你使用代理,或者你也可能出于各种原因使用代理,也有一些环境会默默拦截你的网络流量,并为你代理,不管你想要的是什么。
3.3.14 速率限制
为了防止 curl 占用全部的带宽,可以为 curl 限制带宽,使用 –limit-rate [speed] 让不超过指定的某个速度,速率可限制值可以包含一个后缀字母,K 表示千字节,M 表示兆字节,G 表示千兆字节。
curl www.baidu.com --limit-rate 200k
指定的限定速率是指整个传输过程中 最大平均值,也就是说,curl 有可能在某些很 短的时间段 内使用高于指定速率的传输速率,但是平均速率不会超过指定速率。
3.3.15 最大文件
如果要确保 curl 命令行不会下载过大文件,那么可以令 curl 在开始下载前就停止此操作,前提是 curl 要在传输前知道文件大小!这样做是为了避免占用太多带宽、花费太长时间或是因为你的硬盘没有足够的存储空间:
–max-filesize 文件
curl --max-filesize 100000 www.baidu.com
在很多情况下,curl 无法在传输开始前确定文件大小,那么这个选项就不会产生任何影响, 即使下载的内容可能大于指定的数量。
3.3.16 Metalink
Metalink 是一种文件描述标准,用于告诉客户端有多个位置保存了相同的内容。然后客户端可以选择从一个或多个位置下载内容。
curl 支持 Metalink 格式,可以通过 –metalink 选项来指定。指定的 URL 应该指向一个 Metalink 文件,如下所示:
curl --metalink example.com/example.metalink
如果错误,curl 将会使用 Metalink 文件中列出的镜像进行故障转移。下载完成后再验证文件的哈希值。Metalink 文件会下载到内存中,并在内存中处理,不会保存到本地文件系统中。
3.3.17 在文件系统中保存元数据
将下载的内容保存到文件时,可以通过 --xattr
选项告诉 curl 将某些文件元数据也保存在 “扩展文件属性”中。这些扩展属性是保存在文件系统中的标准化的名称和值,前提是文件系统和操作系统支持扩展属性。
目前,URL 保存在 xdg.origin.url 属性中,HTTP 的 Content-Type 保存在 mime_type 属性中。如果指定了这个选项,但文件系统不支持扩展属性,则会发出警告。
3.3.18 –raw
如果使用 --raw
选项,curl 会禁用所有内部的 HTTP 内容解码或传输编码,取而代之的是传输未经修改的原始数据。
3.3.19 失败次数
通常 curl 只会尝试执行一次传输,不成功则返回错误。你可以使用 –retry 选项让 curl 重试失败的传输。
如果尝试执行传输时返回临时错误,那么 curl 将在放弃之前重试指定的次数。如果将数字设为 0(默认值),curl 将不会进行重试。临时错误可能是:超时、FTP 4xx 响应码 或 HTTP 5xx 响应码。
curl 在开始重试传输前会先等待一秒,对于后续的重试,等待时间加倍,直到达到 10 分钟, 然后剩余的重试延迟就是 10 分钟。--retry-delay
选项可以禁用这种指数退避算法,并设置自己的重试延迟。–retry-max-time 选项可以限制所有重试的总时间。–max-time 选项用于指定单个传输允许的最长时间。
3.3.20 恢复下载和下载范围
在恢复下载时,curl 会先检查本地已存在的文件的大小,然后向服务器请求剩余的内容,并追加到本地文件中。curl 还允许指定自定义恢复点,这些恢复点对应的内容可能不存在于本地。
curl 支持几种协议的恢复下载。-c 或 –continu-at 选项可以告诉 curl 从哪里开始传输,选项的值可以是一个普通的数字字节偏移量,或者使用字符串 - 让 curl 根据它所知道的信息自己决定从哪里开始传输。
如果使用 -,那么 curl 将基于目标文件确定本地已存在的数据量,并将其作为向服务器请求更多数据的偏移量。
从字节偏移为 100 的位置开始下载 FTP 文件:
curl --continue-at 100 ftp://example.com/bigfile
继续之前终端的下载:
curl --continue-at http://example.com/bigfile -O
可以向远程服务器请求特定字节范围的内容。例如,只需要从偏移量 100 开始的 1000个字节,以避免下载整个巨大的远程文件:
curl --range 100-1099 http://example.com/bigfile
3.4 上传
上传是指将数据发送到远程服务器。每种协议的上传方式都不一样,有些协议甚至支持不同的上传方式。
3.4.1 支持上传的协议
你可以使用以下协议上传数据: FILE、FTP、FTPS、HTTP、HTTPS、IMAP、IMAPS、SCP、SFTP、SMB、SMBS、SMTP、SMTPS 和 TFTP。
3.4.2 HTTP 提供了几种“上传”方式
HTTP(HTTPS)提供了几种数据上传方式,而 curl 也为上传提供了简单的命令行选项, 其中有三种常见的方式,后文将逐一介绍。
有意思的是,在 HTTP 中,上传也可以是下载,它们属于同一个操作。事实上,很多下载是通过 HTTP POST 开始的。
3.4.3 POST
POST 是 HTTP 的一个方法,用于将数据发送给接收数据的 Web 应用。例如,它是 Web HTML 表单最常用的方法。通常它会向接收者发送相对较小的数据块。
上传类型通常用 -d 或 –data 选项指定,除此之外,还有其他一些设定方式。
3.4.4 multipart formpost
multipart formpost 通常用于涉及文件上传的 HTML 表单。这种类型的上传也属于 HTTP POST,但会根据一些特殊规则发送格式化的数据,因此被称为 “multipart”。因为它以完全不同的方式发送格式化数据,所以你无法自己选择使用哪种类型的 POST,这完全取决于接收服务器期望和可以处理什么内容。
-F 选项可用于指定使用 HTTP multipart formpost。
3.4.5 PUT
上传类型 HTTP PUT 会发送一个完整的资源,并将其保持原样放在远程站点,甚至可以替换那里已有的资源。目前,PUT 是 Web 使用得最少的一种 HTTP 上传方式,而且大多数 Wb 服务器并没有启用 PUT。可以使用 -T 选项发送要上传的文件:
curl -T uploadthis www.example.com/
3.4.6 FTP 上传
在使用 FTP 时,你可以看到将要访问的远程文件系统。你可以准确地告诉服务器你想要在哪个目录放置上传文件以及要使用哪个文件名。如果你指定的 URL 尾部是一个斜杠,那么 curl 会将本地文件名附加到 URL 后面,这样它就变成了远程的文件名:
curl -T uploadthis ftp://www.example.com/
3.4.7 SMTP 上传
发送电子邮件其实也是一种“上传”,对于 curl 来说确实如此。将邮件上传到 SMTP 服务器。在使用 SMTP 时,需要在邮件中指定需要的标头(To:、From:、Date: 等),因为 curl 不会自己添加这些东西。
这一节没有什么可介绍的,贴代码吧,很少有人会用,不会有人用这个发邮件吧?
curl -T mail smtp://mail.example.com/ --mail-from user@example.com
3.4.8 上传进度条指示器
curl 提供的通用进度指示器也适用于上传。但需要注意的是,将输出发送到 stdout 时,进度指示器会被自动禁用,并且 curl 支持的大多数协议在上传时也会输出一些东西。因此,可能需要显式地将服务器返回的数据重定向到一个文件中(使用 shell 重定向 >
、-O 或类似的选项),这样才能显示上传进度指示器。
3.4.9 速率限制
上传的速率限定和 [下载](#3.3.14 速率限制) 是一样的,实际上,curl 只有一个用于限制两个方向速度的速率限定机制。
3.8 代理
代理是代表客户端执行某项操作的机器或软件。可以将它视为中间人,位于你和目标服务器之间。你连接的是这个中间人,而不是实际的远程服务器。
3.8.1 发现代理
有些网络要求使用代理,这样才能访问互联网或者自己感兴趣的特殊网络。出于政策或技术方面的考虑,网络管理员会在网络中引入代理。
3.8.2 PAC
某些网络环境为不同场景提供了不同类型的代理,浏览器为此提供了一种名为 “代理自动配置”(Proxy Auto Config,PAC)的定制化处理方式。curl 不支持使用 PAC ,需要给 curl 指定代理。
3.8.4 HTTP
HTTP 代理是客户端用来通过 HTTP 完成传输的代理。默认情况下,curl 假设使用了 -x 或 –proxy 选项指定的主机就是 HTTP 代理,没有指定端口的话,默认使用 3128 端口(历史原因)。
curl -x 192.168.1.1 www.baidu.com
3.8.5 HTTPS 和代理
HTTPS 能为客户端和服务端提供安全的端到端隐私,为了在使用 HTTP 代理是仍然能够提供这种安全隐私,HTTP 协议提供了一种特殊请求,curl 可以用它设置一个通道,可以对流量进行加密和验证(connect)。
curl -x proxy.example.com:80 https://example.com/
3.8.6 MITM 代理
MITM 是 Man-n-The-Middle(中间人)的简写。想要对TLS加密流量进行监控的公司通常会在“企业环境”和其他地方部署 MTM 代理。MITM 要求用户在客户端安装自定义“信任根”(CA证书),代理将会终结来自客户端的所有 TLS 流量,然后模拟远程服务器并充当代理。接下来,代理会返回由自定义CA签名的生成证书。这类代理通常会捕获从客户端发到远程计算机TCP443端口的所有流量。在这样的网络中运行,curl 无法绕过 MITM 代理。
3.8.7 HTTP 代理与非 HTTP 代理
HTTP 代理”意味着代理本身使用的是HTTP协议。HTTP代理主要用于代理HTTP流量,但也支持其他协议,比如FTP。
curl -x http://proxy.example.com ftp://ftp.example.com/file.txt
这里即使代理成功了,curl 也不会真正的使用 FTP,因此 FTP 的相关特性将不起作用,可以考虑 “穿过” HTTP 代理。
3.8.8 HTTP 代理通道
大多数 HTTP 代理允许客户端“穿过”它,到达另一端的服务器。通过 HTTP 代理执行 HTTPS 传输就是一个很好的示例。可以通过 -p 或 –proxytunnel 选项让 curl 穿过 HTTP 代理。代理一般不会让连接其他端口(管理员设置),如果可以允许连接到随机端口,可以 “正常” 使用其他协议,如:
curl -x http://proxy.example.com ftp://ftp.example.com/file.txt -p
3.8.9 SOCKS 类型
SOCKS 是一种代理协议,curl 支持 SOCKS4 和 SOCKS5,每种版本都有两种使用方法。可以通过 -x 选项指定 SOCKS 版本,对于这种情况,给定的代理主机的 scheme 部分就是 SOCKS 版本,也可以使用单独的选项来指定。
与 SOCKS4 类似,SOCKS4a 只是不在本地解析主机名。
SOCKS4:
curl -x socks4://proxy.example.com http://www.example.com/
curl --socks4 socks4://proxy.example.com http://www.example.com/
SOCKS4a:
curl -x socks4a://proxy.example.com http://www.example.com/
curl --socks4 socks4a://proxy.example.com http://www.example.com/
与SOCKS5 类似,SOCKS5-hostname只是不在本地解析主机名.
SOCKS5:
curl -x socks5://proxy.example.com http://www.example.com/
curl --socks5 socks5://proxy.example.com http://www.example.com/
SOCKS5-hostname 会将主机名发送给服务器,因此不在本地解析主机名:
curl -x socks5h://proxy.example.com http://www.example.com/
curl --socks5a socks5://proxy.example.com http://www.example.com/
3.8.10 代理身份证验证
HTTP 代理可以要求进行身份验证,因此 curl 需要向代理提供适当的凭着,否则代理会返回 407 HTTP 响应码,可以使用 -U user:password
或 --proxy-user user:paasword
选项来设置代理身份验证的用户名和密码:
curl -U daniel:secr3t -x proxy.example.com:80 https://example.com/
还可以使用 --proxy-digest
、--proxy-negotiate
、--proxy-ntlm
指定使用的方法。
curl -U daniel:secr3t -x proxy.example.com:80 https://example.com/ --proxy-ntlm
--proxy-anyauth
curl 自己去找认证的方法。
3.8.11 使用 HTTPS 连接代理
HTTP 和 SOCKS 是明文协议,会导致某些人可以通过代理窃取流量,使用 HTTPS 连接代理,从而建立一个安全的加密连接,这样就不会被监视。
3.8.12 代理环境变量
curl 会在运行前检查是否存在某些特殊的环境变量,然后根据这些变量决定是否使用代理。可以通过 [scheme]_proxy
变量来指定代理。
http_proxy=http://proxy.example.com
curl -v http://www.example.com/
[scheme]_proxy
还可以设置ftp_proxy
、https_proxy
等,所有的环境变量名可以是大写,如HTTP_PROXY
。也可以通过
ALL_PROXY
设置所有的协议。
3.9 退出状态
cURL 项目上做了很大努力,它可以在出现问题时返回一个可用的退出码,如果一切正常则返回0(零)。
如果编写了一个调用 curl 的 shell 脚本或批处理文件,可以通过检查返回码来检测命令是否有问题。
3.9.1 可用的退出码
状态码太多无法写出,可参考:命令状态码返回码
3.9.2 错误消息
以非零状态码退出时,curl 还会输出一个错误消息(除非使用了 -silent 选项)。这个错误消息可能会包含一些额外的信息,因此,相同的错误码可能会与不同的错误消息一起出现。
3.9.3 “未使用”
前面的状态码列表包含了很多标记为 “未使用” 的数字。这些状态码没有用于现代版本的 curl 中,但过去曾经被使用过或打算使用。它们很可能会用于未来的 curl 版本中。
3.10 FTP
SCP 和 SFTP 都是建立在 SSH 之上的协议,SSH 是一种类似于TLS的安全加密数据协议,但在某些方面有所不同。例如,SSH 不使用任何类型的证书,而是使用公钥和私钥。如果使用得当,SSH 和 TLS 都可以提供强大的安全传输。
当连接到 SFTP 或 SCP 主机时,curl 会先确认主机的密钥散列已存在于已知主机的文件中,否则它将拒绝后续操作,如果known_hosts中存在正确的散列,curl就会开始执行传输。要想强制 curl 跳过检查,可以使用 -k 或 –insecure 选项。在使用这两个选项时必须非常小心,因为这样有可能检测不到中间人的攻击。
3.15 复制为 curl 命令
这些工具将为你提供命令行以及需要在请求中发送的静态cookie内容,也就是通过浏览器请求发送的cookie内容。你很可能希望重写命令行,以便动态修改服务器在之前的响应中告诉你的cookie内容,等等。
需要使用-F选项时,复制为curl命令行这一功能生成的命令行并不好用,于是curl提供了–data-binary选项,这个选项可以包含mime分隔符分隔的字符串等。
第 4 章 用 curl 执行 HTTP 操作
根据用户反馈以及在 curl 的整个生命周期当中,HTTP 一直是 curl 最重要和最常用的协议。
考虑到这篇文章中容不下这么多字,另出一篇文章来记载。
4.6 HTTP POST
POST 是为将数据发送到 Web 应用而发明的 HTTP 方法,也是 HTML 表单中最常用的方法。 它通常会向接收者发送相对少量的数据块。
在表单中填充好数据后,浏览器以“URL编码”的形式(以&符号分隔的一系列键值对)将数据发送出去。可以用 curl 的 -d 或 –data 选项发送这样的数据,如下所示:
curl -d 'name=admin&shoesize=12' http://example.com/
curl -d name=admin -d shoesize=12 http://example.com/ #curl会用&将他们串联起来
如果不合适作为字符串放在命令行中,还可以从文件中读取:
curl -d @filename http://example.com/
4.6.1 Content-Type
用 curl 的 -d 选项发送 POST 请求时,请求中默认会包含一个类似 Content-Type:application/x-www-form-urlencoded
这样的标头。典型的浏览器在发送 POST 请求时也会使用这个标头。
如果默认标头对你来说还不够好,则可以用其他标头来代替。例如,如果想将 JSON POST 到服务器,并且准确地告诉服务器你发送的内容是什么类型,可以参见以下代码:
curl -d '{json}' -H 'Content-Type:application/json' http://example.com/
4.6.2 POST 二进制内容
用 -d 选项从文件读取内容时,回车符和换行符将被移除。如果想让 curl 从文件读取二进制内容,可以使用 –data-binary:
curl --data-binary @filename http://example.com/
也就是说 –data-binary 不会替换回车符和换行符,会直接将数据发送给服务端。
4.6.3 URL 编码
URL 编码(也称为百分号编码)是一种编码数据的方式,这种方式允许数据以合法的形式出现在 URL 中。用 application/x-www-form-urlencoded
发送 POST 请求时通常会使用这种编码方式,curl 用 –data 和 –data-binary 选项发送内容时不会进行编码。
如果我们需要发经编码的数据,curl 提供了 –data-urlencode 选项。这个选项提供了几种不同的方式对提供的数据进行 URL 编码。
curl --data-urlencode 'name=John Doe' http://example.com/api
curl --data-urlencode "@data.txt" http://example.com/api #从数据文件中读取并发送
curl --data-urlencode user@data.txt http://example.com/api #user值为data.txt里的内容
curl --data-urlencode "=user name=John Doe" http://example.com/api #发送user name =John Doe 必须加在前面加 =
4.6.4 转为为 GET
可以将 POST 请求加上 -G (–get)变为 GET 请求,它将 -d 选项指定的数据附加到 URL 右边,并使用 “?” 分隔,然后让 curl 用 GET 方法发送数据。
curl --data-urlencode 'name=John Doe' http://example.com/api --get
4.6.5 Expect:100-continue
在 HTTP 协议里,当客户端要发送较大的请求体(比如上传大文件)时,它可以先发送一个包含 Expect: 100-continue
请求头的请求给服务器。
服务器接收到这个请求后,如果愿意接收客户端后续的请求体,就会返回一个状态码为 100 Continue
的响应;要是服务器由于某些原因(例如权限不足、请求格式错误等)不想接收请求体,就会直接返回一个错误响应(如 400 Bad Request)。
客户端根据服务器的响应来决定是否继续发送请求体。如果收到 100 Continue
,就继续发送请求体;若收到错误响应,则停止发送。
curl -H Expect: -d "@large_file.txt" http://example.com/upload
curl -H "Expect: 100-continue" -d "@large_file.txt" http://example.com/upload
很多服务器对 100-continue 支持并不友好,curl 收到第一个响应前等待1000毫秒,然后继续发送数据。发送内容非常少时(低于1千字节),curl 禁止使用 Expect: 标头,因为 “浪费”。
4.6.6 分块编码的 POST
与HTTP 1.1 服务器通信时,可以让 curl 在不使用 Content-Length:标头的情况下发送请求正文。通过使用分块传输编码,curl 将逐块发送 POST 数据,每个数据块中会包含块的大小。
curl -H "Transfer-Encoding:chunked" -d "a123" http://example.com
4.6.7 隐藏的表单字段
HTML 中可以对表单进行隐藏,curl 中需要提取响应的表单字段才能发送。
4.6.8 了解浏览器都发送了些什么
可以通过抓取浏览器的网络请求抓取数据,可以通过抓包工具将浏览器发送表单保存起来。
4.6.9 Javascript 和表单
针对自动“代理”或脚本的常见解决方法是让包含HTML表单的页面使用JavaScript设置某些输入字段(通常是隐藏字段)的值。通常,加载页面或按下提交按钮时会执行一些JavaScript 代码,并设置一个魔术值,服务器在确定提交是否有效前会对其进行验证。
4.7 HTTP multipart formpost
multipart formpost 是指 HTTP 客户端在 HTML 表单的 enctype 属性被设置为 “multipart/form-data”时所发送的内容,它是一个HTTP POST 请求,其中请求正文被格式化为一系列 ”part“,并以 MIME 边界字符串为分隔。
4.7.1 使用 curl 发送表单
使用 curl 时,可以通过 -F(–form)选项添加每个单独的multipart,然后继续为表单的每个字段添加一个 -F。
curl -F file=@filename http://example.com/upload
注意:-F 上传文件为 = 后再加文件路径,和 -d 上传文件有所区别,-d 为从文件中获取值。
4.7.2 生成 HTTP 内容
111
4.7.3 Content-Type
-F 会默认包含 Content-Type 标头,标头信息是 multipart/form-data
,后面是 MIME 边界字符串。当然也可以自行修改,如果做了修改,curl 会自动将边界字符串附加到被替换的标头中。你无法修改边界字符串,因为 curl 需要用它来生成 POST 数据。
替换标头,可使用 -H ,如图所示:
curl -F 'name=Dan' -H 'Content-Type:multipart/magic' https://example.com
4.8 -d 与 -F
这两个选项都会将指定的数据发送到服务器。不同之处在于如何格式化数据。 大多数情况下,接收端会接收特定格式的数据,并期望发送方可以正确格式化数据。客户端无法只使用自己选定的格式。
4.8.1 HTML Web 表单
表单默认的 enctype 是 application/x-www-form-urlencoded
(因为是默认值,所以很少在HTML中显式指定)。浏览器将输人字段“URL编码”成键值对,避免出现不安全的字符。通常将其称为常规 POST,在 curl 中可以通过 -d 选项实现。
如果 <form>
标签包含了enctype= multipart/form-data
,那就是要浏览器将数据作为 multipart formpost 发送,这与curl 中的 -F 选项等效。当表单中包含(用于文件上载的) <input type=file>
标签时,通常会使用这个方法。
4.8.2 HTML 之外的 POST
curl 的 -d 选项不会改变数据,也不会对数据进行编码,它只会发送你要它发送的内容。注意 -d 选项默认使用的 Content-Type,因为它可能不是你想要的。
4.9 重定向
4.9.1 HTTP 重定向
“重定向”是HTTP的基本组成部分。这个概念在1996年发布的第一个规范(RFC1945)中就已存在,并从那时就一直被广泛使用。
进行重定向时需要发送一个Location:标头,其中包含新的URI,可以是绝对路径或相对路径。
4.9.2 永久重定向和临时重定向
重定向是持续有效还是仅在当下有效?要想通过一个 GET 方法将用户永久重定向到资源 B, 则可以返回 301 响应码。用户代理(浏览器)需要缓存这些信息,并从现在开始使用新的 URI。
临时重定向的返回码是 302。服务器希望客户端将GET请求发送给B,但客户端不应该缓存这个信息,下一次仍然使用原始的URI。
实际上 303 与 302 非常相似。它不会被缓存,只是明确客户端将在下一个请求中使用 GET。
注意:301 和 302 响应码会让浏览器在下一个请求中使用GET,如果最开始使用的是P0ST,下一个请求会被改为GET。
这三个响应码是 HTTP/1.0 规范中 仅有 的重定向响应码。
curl 并不会记住或缓存任何重定向信息,因此永久重定向和临时重定向对 curl 来说并没有什么区别。
4.9.3 让 curl 遵循重定向
般来说,curl 只会做一些基本的操作,除非你告诉它,否则默认情况下它不会遵循 HTTP 重定向。可以通过 -L 或 –location 选项让它遵循HTTP重定向。curl 默认最多会执行 50 次重定向。设置最大次数限制是为了避免陷入无限循环。可以通过 –max-redirs 选项修改最大重定向次数。
4.9.4 GET 还是 POST
HTTP1.1 新增了一个响应码,307 ,307 是一个(较旧的)响应码,它告诉客户端在下一个请求中临时使用 P0ST。这个重定向不会被客户端缓存,因此下一个请求仍然会发给 A。
如果要告诉客户端 “你请求的URI被永久重定向到B,从现在开始,请将你的P0ST请求发送到B”,那么服务器就会返回308响应码。不过,308响应码是最近才定义的(规范于2014年6月发布),因此旧的客户端可能无法正确处理它!
4.9.5 决定在重定向中使用哪种方法
世界上有一些 Web服务希望客户端将 POST 发送到原始 URL,并在返回 301、302 或 303 响应码后,仍然希望 HTTP 客户端在下一个请求中继续使用 P0ST。但在默认情况下,浏览器不会这么做,curl 也不会。
可以通过–post301、–post302 和 –post303 三个选项让curl 在收到 30x 响应后不将非 GET请求方法改为GET。
4.9.6 重定向到其他主机
在使用 curl 时,你可能会为特定网站提供用户名和密码等凭证,但由于 HTTP 重定向可能会转移到其他主机,curl 会对发送给其他主机的内容加以限制。
如果希望凭证也被发送到后面的主机,即使与原始主机不同(这么做大概是因为你信任它们并且知道没有任何害处),则可以使用 --location-trusted
选项。
4.9.7 非HTTP重定向
浏览器支持更多的重定向方法,有时这会让cul用户感到困惑,因为cul可能不支持或无法识别这些方法。
4.9.8 HTML 重定向
可以通过纯 HTML 让浏览器进行重定向方法。使用 <meta>
标签。
<meta http-equiv="refresh" content="0;url=http://example.com">
meta 标签也只重定向 GET 请求,curl 不解析 HTML 内容,所以对 curl 无效。
4.9.9 Javascript 重定向
JavaScript 也提供了用于指示浏览器转向另一个网站的方法,如果愿意,也可以把它叫作重定向。
curl 不解析 HTML 内容,所以对 curl 无效。
小结
第一次尝试将一本书籍内容的概要摘选出来写博文,这样再摘选的过程中相当于是阅读书籍了,这样尝试了一下,发现阅读效率还是很高的,一本书可以很快阅读完。当然我也是只记录了我认为重要章节,中间序号有中断的证明我认为中间的不重要,或很难用到。