温柔是一种力量,可能转化成爱,可能变成一个防护罩,也可能是支持两个人距离的一种松紧。如何看待温柔,温柔便转化成你心目中的那个模样 小马
URL
之所以称为curl,是因为curl的名字中包含了URL(Uniform Resource Locator,统一资源定位符)。URL就是curl的操作对象。URL就是通常使用的网址字符串,如经常看到的以http://为前缀或以www开头的网址。
我给截图了一下
严格来说,URL是之前使用的名称,URI(Uniform Resource Identifier,统一资源标识符)才是更现代、更正确的叫法。RFC 3986给出了它们的语法定义。
curl接受“URL”作为输入,但实际上是“URI”。curl支持的大多数协议也有相应的URI语法文档,这些文档描述了这些URI格式的工作原理。
curl假定你会传给它一个有效的URL,它只对格式进行有限的检查,以提取执行操作所需要的信息。你可能会将包含非法字符的URL传给curl,但curl并不会注意到,也不关心这些,它只会继续执行自己的操作。
scheme
我们看看是什么意思呢
就是这个东西
URL以“scheme”作为开头,scheme是“http://”这部分内容的官方名称,用于告诉curl传入的URL使用了哪个协议。scheme必须受当前curl版本支持,否则curl将显示错误消息并退出。此外,scheme既不能以空格开头,也不能包含空格,你打个http都能打错。。。。
scheme分隔符
“://”(一个冒号和两个斜杠)将scheme标识符与URL的其余部分分开。有些URL只包含一个斜杠,但curl不支持这种格式。关于斜杠的数量,需要注意的事项有两个。
curl允许一些非法语法,并尝试在内部纠正它们,因此它也可以理解并接受一些带有一个或三个斜杠的URL,即使它们的格式不正确。curl这么做的原因是,浏览器已经开始支持这些URL,进而导致这种URL大量存在。
代码语言:javascript复制file://类型的URL写作file://<hostname>/<path>
但主机名部分只能是localhost、127.0.0.1或空白(什么都没有)。
代码语言:javascript复制 file://localhost/path/to/file
file://127.0.0.1/path/to/file
file:///path/to/file
如果在主机名部分使用其他主机名,curl将返回错误。
注意以上的第三个示例
代码语言:javascript复制(file:///path/to/file)
,路径前面有三个斜杠。这也是一个常见错误,但浏览器允许用户使用这种错误语法,因此它被视为例外。Windows系统上的curl也允许这种不正确的格式。
代码语言:javascript复制 file://X:/path/to/file
其中X是Windows的磁盘分区符。
不使用scheme
为方便起见,curl还允许用户省略URL的scheme部分。curl会根据主机名的第一部分猜测要使用哪种协议。这是一种非常基本的猜测,因为它只检查主机名的第一部分是否与一组协议中的某个协议匹配,并假定你打算使用的就是这个协议。这主要基于传统的服务器命名方式。可以通过这种方式检测的协议包括FTP、DICT、LDAP、IMAP、SMTP和POP3。没有提供scheme的其他URL将默认使用HTTP。
你可以通过--proto-default选项将默认协议修改为HTTP以外的其他协议。
用户名和密码
scheme后面可以跟用户名和密码。现在通常不建议使用这种语法,因为这样很容易在脚本或其他地方泄露这些信息。例如,使用给定的用户名和密码列出FTP服务器目录中的内容:
代码语言:javascript复制 curl ftp://user:password@example.com/
在URL中显示用户名和密码只是可选项,curl还允许在URL之外,即通过正常的命令行选项来提供这些信息。
主机名或地址
URL的主机名部分只是一个可以解析为数字IP地址的名字,或者是数字IP地址本身。在指定数字IP地址时,可以使用IPv4地址。
代码语言:javascript复制curl http://127.0.0.1/
如果使用的是IPv6地址,则需要将其放在方括号中。
代码语言:javascript复制 curl http://[::1]/
如果使用的是主机名,系统解析器会将主机名转换为IP地址。这通常需要在/etc/hosts文件(或等效文件)中进行本地域名查找。
端口号
每个协议都有一个“默认端口”,除非特别指定了端口号。在URL中指定端口号时,先在主机名后面添加一个冒号,然后是十进制的端口号。例如,我们可以请求端口8080上的HTTP文档。
代码语言:javascript复制 curl http://example.com:8080/
将主机名指定为IPv4地址:
代码语言:javascript复制 curl http://127.0.0.1:8080/
将主机名指定为IPv6地址:
代码语言:javascript复制 curl http://[fdea::1]:8080/
路径
每个URL都包含一个路径。如果没有指定,则默认使用“/”。路径将被发送给指定的服务器,用于识别要请求的资源。
路径的用法取决于具体的协议。以下展示了如何使用匿名用户从FTP服务器获取README文件。
代码语言:javascript复制 curl ftp://ftp.example.com/README
对于具有目录概念的协议,可以在URL尾部以一个斜杠表示它是目录,而不是文件。因此,请求FTP服务器的目录列表时需要使用斜杠。
代码语言:javascript复制 curl ftp://ftp.example.com/tmp/
FTP类型
这是一个没有被广泛使用的特性。
用于标识FTP服务器文件的URL提供了一个特性来告诉客户端(这里是curl)资源的文件类型。这是因为FTP可以改变传输模式,在不同的模式下使用不同的处理方式。
通过在URL中附加“; type=A”,你可以告诉curl当前的FTP资源是ASCII类型。你可以从example.com根目录获取ASCII类型的foo文件,如下所示。
代码语言:javascript复制 curl "ftp://example.com/foo; type=A"
curl默认为FTP使用二进制传输模式,但是你也可以在URL中通过type=I来指定二进制类型。
代码语言:javascript复制 curl "ftp://example.com/foo; type=I"
如果你传给curl的类型是D,那么就是表明请求的资源是一个目录。
代码语言:javascript复制 curl "ftp://example.com/foo; type=D"
这可以作为目录的替代格式,不需要像之前那样在路径尾部添加斜杠。
片段
URL中还可以包含“片段”,这通常由井号(#)和网页中的特定名字组成。curl可以支持带有片段的URL,但实际上片段并不会被发送出去,因此,无论是否存在,它对curl的操作并没有任何影响。
浏览器的“地址栏”
现代Web浏览器的“地址栏”中一般使用的不是URL或URI。实际上,它们主要使用IRI,也就是URI的超集,以支持国际化(如支持非拉丁符号)。它们还会处理空格、编码地址等,但规范中并没有说明这些事情应该由客户端完成。
地址栏只是一个简单的界面,让人可以输入和看到URI风格的字符串。
有时你在浏览器地址栏中看到的内容与传给curl的内容存在很大差别。
多个选项和多个URL
如上所述,curl支持数百个命令行选项和无限数量的URL。如果你的shell或命令行系统能够支持,那么传给curl的命令行长度实际上是没有限制的。
curl首先会解析整个命令行,应用给定的命令行选项,然后(按从左到右的顺序)遍历URL并执行相应操作。
对于某些选项(如告诉curl将输出内容保存在哪里的-o或-O),你可能希望为每个URL单独指定。
curl会在处理完最后一个URL后返回一个退出码。想让curl在第一次出现错误时就退出,则可以使用--fail-early选项。
URL的单独选项
前面介绍了curl如何解析命令行的所有选项并将它们应用于所有的URL。
curl还提供了另一个选项(--next,短格式为-;),用于在一组选项和URL之间插入间隔。当命令行解析器遇到--next选项时,它会将后面的选项应用于下一组URL。因此,--next选项其实是一组选项和URL之间的分隔符。使用多少个--next选项取决于实际的需要。
例如,我们向一个URL发起HTTP GET请求,再向另一个URL发起HTTP POST请求,然后向第三个URL发起HEAD请求。以下代码将这些写在一个命令行中。
代码语言:javascript复制
curl --location http://example.com/1--next
--data sendthis http://example.com/2--next
--head http://example.com/3
去除--next选项会使得以上命令行变成非法的,因为curl会尝试将POST和HEAD结合在一起。
代码语言:javascript复制 Warning: You can only select one HTTP request method! You asked for both POST
Warning: (-d, --data) and HEAD (-I, --head).
连接重用
即使是在高带宽的网络中,建立TCP连接(尤其是TLS连接)也是一个缓慢的过程。
curl在内部维护着一个连接池,这可以让之前使用过的连接继续存活一段时间,因此后续发给相同主机的请求可以重用这些已经建立的连接。
连接池中的连接可以在curl运行期间保持活跃状态,但最好还是在同一个命令行中完成多次传输,而不是单独运行多个curl命令行。