HTTP权威指南(Web的基础篇Day2)

前言


继续

HTTP:Web 的基础

URL与资源

浏览因特网资源

URI 是一类更通用的资源标识符,URL 实际上是它的一个子集。URI 是一个通用的概念,由两个主要的子集 URL 和 URN 构成,URL 是通过描述资源的位置来标识资源的,而 URN 则是通过名字来识别资源的,与它们当前所处位置无关。

HTTP 规范将更通用的概念 URI 作为其资源标识符,但实际上,HTTP 应用程序处 理的只是 URI 的 URL 子集

比如说,你想要获取 URL https://valyn.vercel.app/post/21562.html。 那么 URL 分以下三部分。

  • URL 的第一部分(https)是 URL 方案(scheme)。方案可以告知 Web 客户端怎样访问资源。在这个例子中,URL 说明要使用 HTTP 协议。
  • URL 的第二部分(www.valyn.vercel.app)指的是服务器的位置。这部分告知 Web 客户端资源位于何处。
  • URL 的第三部分(/post/21562.html)是资源路径。路径说明了请求的是 服务器上哪个特定的本地资源。

image-20231005170619684

URL 可以通过 HTTP 之外的其他协议来访问资源。它们可以指向因特网上的任意资源,或者个人的 E-mail 账户:

mailto:president@whitehouse.gov

或者通过其他协议(比如 FTP 协议)访问的各种文件:

ftp://ftp.lots-o-books.com/pub/complete-price-list.xls

或者从流视频服务器上下载电影:

rtsp://www.joes-hardware.com:554/interview/cto_video

URL 提供了一种统一的资源命名方式。大多数 URL 都有同样的:“方案 :// 服务器 位置 / 路径”结构。因此,对网络上的每个资源以及获取这些资源的每种方式来说, 命名资源的方法都只有一种,这样不管是谁都可以用名字来找到这个资源了。但是, 事情并不是一开始就是这样的。

URL的语法

URL 提供了一种定位因特网上任意资源的手段,但这些资源是可以通过各种不同的 方案(比如 HTTP、FTP、SMTP)来访问的,因此 URL 语法会随方案的不同而有所不同。 这是不是意味着每种不同的 URL 方案都会有完全不同的语法呢?实际上,不是的。 大部分 URL 都遵循通用的 URL 语法,而且不同 URL 方案的风格和语法都有不少重叠。

大多数 URL 方案的 URL 语法都建立在这个由 9 部分构成的通用格式上:

image-20231005171130257

几乎没有哪个 URL 中包含了所有这些组件。URL 最重要的 3 个部分是方案(scheme)、 主机(host)和路径(path)。

image

方案——使用什么协议

方案实际上是规定如何访问指定资源的主要标识符,它会告诉负责解析 URL 的应用程序应该使用什么协议。在我们这个简单的 HTTP URL 中所使用的方案就是 http。 方案组件必须以一个字母符号开始,由第一个“:”符号将其与 URL 的其余部分分 隔开来。方案名是大小写无关的,因此 URL“http://www.joes-hardware.com”和 “HTTP://www.joes-hardware.com”是等价的。

主机与端口

要想在因特网上找到资源,应用程序要知道是哪台机器装载了资源,以及在那台机 器的什么地方可以找到能对目标资源进行访问的服务器。URL 的主机和端口组件提供了这两组信息。

主机组件标识了因特网上能够访问资源的宿主机器。可以用上述主机名(www.joeshardware.com),或者 IP 地址来表示主机名。比如,下面两个 URL 就指向同一个资 源——第一个 URL 是通过主机名,第二个是通过 IP 地址指向服务器的: http://www.joes-hardware.com:80/index.html http://161.58.228.45:80/index.html 端口组件标识了服务器正在监听的网络端口。对下层使用了 TCP 协议的 HTTP 来说,默认端口号为 80。

用户名和密码

更有趣的组件是用户和密码组件。很多服务器都要求输入用户名和密码才会允许用 户访问数据。FTP 服务器就是这样一个常见的实例。这里有几个例子:

ftp://ftp.prep.ai.mit.edu/pub/gnu

ftp://anonymous@ftp.prep.ai.mit.edu/pub/gnu ftp://anonymous:my_passwd@ftp.prep.ai.mit.edu/pub/gnu http://joe:joespasswd@www.joes-hardware.com/sales_info.txt

第一个例子没有用户或密码组件,只有标准的方案、主机和路径。如果某应用程 序使用的 URL 方案要求输入用户名和密码,比如 FTP,但用户没有提供,它通常 会插入一个默认的用户名和密码。比如,如果向浏览器提供一个 FTP URL,但没 有指定用户名和密码,它就会插入 anonymous(匿名用户)作为你的用户名,并发 送一个默认的密码(Internet Explorer 会发送 IEUser,Netscape Navigator 则会发送 mozilla)。

第二个例子显示了一个指定为 anonymous 的用户名。这个用户名与主机组件组合在 一起,看起来就像 E-mail 地址一样。字符“@”将用户和密码组件与 URL 的其余 部分分隔开来。

在第三个例子中,指定了用户名(anonymous)和密码(my_passwd),两者之间由 字符“:”分隔。

路径

URL 的路径组件说明了资源位于服务器的什么地方。路径通常很像一个分级的文件系统路径。比如:

http://www.joes-hardware.com:80/seasonal/index-fall.html

这个 URL 中的路径为 /seasonal/index-fall.html,很像 UNIX 文件系统中的文件系统路径。路径是服务器定位资源时所需的信息。可以用字符“/”将 HTTP URL 的路 径组件划分成一些路径段(path segment)(还是与 UNIX 文件系统中的文件路径类 似)。每个路径段都有自己的参数(param)组件。

参数

对很多方案来说,只有简单的主机名和到达对象的路径是不够的。除了服务器正在 监听的端口,以及是否能够通过用户名和密码访问资源外,很多协议都还需要更多 的信息才能工作。 负责解析 URL 的应用程序需要这些协议参数来访问资源。否则,另一端的服务器可 能就不会为请求提供服务,或者更糟糕的是,提供错误的服务。比如,像 FTP 这样 的协议,有两种传输模式,二进制和文本形式。你肯定不希望以文本形式来传送二 进制图片,这样的话,二进制图片可能会变得一团糟。 为了向应用程序提供它们所需的输入参数,以便正确地与服务器进行交互,URL 中 有一个参数组件。这个组件就是 URL 中的名值对列表,由字符“;”将其与 URL 的 其余部分(以及各名值对)分隔开来。它们为应用程序提供了访问资源所需的所有 附加信息。比如: ftp://prep.ai.mit.edu/pub/gnu;type=d

在这个例子中,有一个参数 type=d,参数名为 type,值为 d。

如前所述,HTTP URL 的路径组件可以分成若干路径段。每段都可以有自己的参数。比如:

http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true

这个例子就有两个路径段,hammers 和 index.html。hammers 路径段有参数 sale,其值为 false。index.html 段有参数 graphics,其值为 true。

查询字符串

很多资源,比如数据库服务,都是可以通过提问题或进行查询来缩小所请求资源类型范围的。

假设 Joe 的五金商店在数据库中维护着一个未售货物的清单,并可以对清单进行查询,以判断产品是否有货,那就可以用下列 URL 来查询 Web 数据库网关,看看编号为 12731 的条目是否有货:

http://www.joes-hardware.com/inventory-check.cgi?item=12731

这个 URL 的大部分都与我们见过的其他 URL 类似。只有问号(?)右边的内容是新出现的。这部分被称为查询(query)组件。URL 的查询组件和标识网关资源的 URL 路径组件一起被发送给网关资源。基本上可以将网关当作访问其他应用程序的访问点。

image-20231005173355711

片段

有些资源类型,比如 HTML,除了资源级之外,还可以做进一步的划分。比如,对一个带有章节的大型文本文档来说,资源的 URL 会指向整个文本文档,但理想的情况是,能够指定资源中的那些章节。 为了引用部分资源或资源的一个片段,URL 支持使用片段(frag)组件来表示一个资源内部的片段。比如,URL 可以指向 HTML 文档中一个特定的图片或小节。 片段挂在 URL 的右手边,最前面有一个字符“#”。比如: http://www.joes-hardware.com/tools.html#drills 在这个例子中,片段 drills 引用了 Joe 的五金商店 Web 服务器上页面 /tools.html 中的一个部分。这部分的名字叫做 drills。 HTTP 服务器通常只处理整个对象,而不是对象的片段,客户端不能将片段传送给服务器。浏览器从服务器获得了整个资源之后,会根据片段来显示你感兴趣的那部分资源。

image-20231005172102921

各种令人头疼的字符

URL 是可移植的(portable)。它要统一地命名因特网上所有的资源,这也就意味着要通过各种不同的协议来传送这些资源。这些协议在传输数据时都会使用不同的机 制,所以,设计 URL,使其可以通过任意因特网协议安全地传输是很重要的。

安全传输意味着 URL 的传输不能丢失信息。有些协议,比如传输电子邮件的简单邮件传输协议(Simple Mail Transfer Protocol,SMTP),所使用的传输方法就会剥去一些特定的字符。为了避开这些问题,URL 只能使用一些相对较小的、通用的安全字母表中的字符。 除了希望 URL 可以被所有因特网协议进行传送之外,设计者们还希望 URL 也可供人类阅读。因此,即使不可见、不可打印的字符能够穿过邮件程序,从而成为可移植的,也不能在 URL 中使用。URL 还得是完整的,这就使问题变得更加复杂了。URL 的设计者们认识到有时人们可能会希望 URL 中包含除通用的安全字母表之外的二进制数据或字符。因此,需要有一种转义机制,能够将不安全的字符编码为安全字符,再进行传输

URL字符集

由于 US-ASCII 的历史悠久,所以其可移植性很好。但是,虽然美国用户使用起来 很便捷,它却并不支持在各种欧洲语言或全世界数十亿人使用的数百种非罗马语言中很常见的变体字符。

认识到对完整性的需求之后,URL 的设计者就将转义序列集成了进去。通过转义序列,就可以用 US-ASCII 字符集的 有限子集对任意字符值或数据进行编码了,这样就实现了可移植性和完整性。

编码机制

为了避开安全字符集表示法带来的限制,人们设计了一种编码机制,用来在 URL 中 表示各种不安全的字符。这种编码机制就是通过一种“转义”表示法来表示不安全字符的,这种转义表示法包含一个百分号(%),后面跟着两个表示字符 ASCII 码的十六进制数。

image-20231005172459031

字符限制

URL 中,有几个字符被保留起来,有着特殊的含义。有些字符不在定义的 USASCII 可打印字符集中。还有些字符会与某些因特网网关和协议产生混淆,因此不赞成使用。

image-20231005172528243

方案的世界

image-20231005172600744

image-20231005172611769

后记