图源:
参考书目
这个新开的博文系列《HTTP学习笔记》的主要参考书籍为,原书为Oreilly出版社出版,中文版是人民邮电出版社发行,属于图灵教育系列图书,品质有保证。此外该书的纸质也很扎实。
因为原书成书于2000年左右,所以大部分涉及HTTP2.0的部分以及对未来的互联网展望的部分都显得相当落伍,但本书的主要内容依然是介绍HTTP1.0协议的方方面面,在这方面是相当扎实和使用的。而且就HTTP协议这个互联网基石一般的技术来说,这么多年过去了,其主要技术并没有发生大的改变。其实计算机技术就是这样,只要还能用,还没有到瓶颈,就大概率不会用新技术去取代,IPv6就是一个例子。
客户端&服务器
通常我们在讨论HTTP的时候,都会以客户端和服务器作为基础场景,这其中客户端指的是一个发送HTTP请求报文的应用,而服务端是一个处理HTTP请求,并返回一个HTTP响应报文的web服务应用。
在一般情况下会简单地将客户端看做是用户PC,而服务端看做是web服务器。
其关系可以用下图表示:
图源:《HTTP权威指南》
资源
HTTP服务器(web服务器)的本质是web资源的“宿主”。
事实上现代的Web服务器的主要职责是负责处理HTTP响应,资源存储的职责会专门由“对象存储服务器”来负责。
说到资源,可能大部分人能想到的是诸如图片、视频、音频等这些“有形”的数字产品,但事实上所有可以通过HTTP响应获取到的内容都可以看做是网络资源:
图源:《HTTP权威指南》
图中的网关(gateway)可以简单理解为各种Web应用。
资源类型
服务器可以提供各种各样的资源这很棒,但随之而来的问题就是浏览器如何处理这些资源?
比如说对于各种格式的视频资源,我们可能希望浏览器直接播放,而对于.torrent
这种种子文件可能需要打开迅雷进行后续下载,在办公场景中更常见的应当是对于.docx
或.pptx
这些office全家桶文件,应当直接调用office打开进行后续的文案处理。
所有的这些,都是通过一个MIME类型来进行区分来实现的。
MIME类型(MIME type)全称Multipurpose Internet Mail Extension(多用途英特网邮件扩展),我知道这个名字听起来非常怪异,事实上该技术最早是用来处理电子邮件服务器上的电子邮件迁移的(大概是用于标记不同的电子邮件附件的格式?)。但因为可以很好的用于标记不同的文件类型,所以被HTTP协议直接拿来继续使用了。
HTTP返回报文中,会将返回数据的MIME类型以报文头的形式附加:
图源:《HTTP权威指南》
上图中image/jpeg
就是一个MIME类型,表示返回的数据是一张JPEG格式的图片。这样接收到数据的HTTP客户端就知道如何处理返回数据了(这里大概率是直接在浏览器中显示图片)。
MIME类型很简单,包含两部分:主要对象类型和子类型,中间通过/
进行连接。
常见的额MIME类型有:
-
text/html
:HTML文本。 -
text/pain
:ASCII文本。 -
image/jpeg
:JPEG格式的图片。 -
image/gif
:GIF格式的图片。 -
application/vnd.ms-powerpoint
:PPT文件。
完整的MIME列表见。
关于更多MIME类型的说明可以见。
URI
要访问Web服务器上的资源,通常要使用一个”HTTP地址”,我们通常称之为URL。
事实上,更准确的说法应当是URI(Uniform Resource Identifier,统一资源标识符),一个URI就可以在互联网中唯一地定位一个资源。
URI包含两种形式:URL和URN。
URL
URL(Uniform Resource Locator,统一资源定位符)是最常见的URI形式:
图源:《HTTP权威指南》
像上图中展示的那样,URL包含有这么几个部分:
-
协议:在示例中是
http://
,此外常见的Web协议还有https
,ftp
是以前常见的协议,但已经因为安全原因被废弃,现代浏览器已经不再支持该协议。 -
端口:不同的协议有不同的默认端口,
http
是80
,https
是443
,如果服务器提供的是默认端口之外的端口进行服务,就需要在URL中指定端口,比如http://www.myweb.com:81/index.html
。 -
主机名:示例中的
www.joes-hardware.com
部分,这部分主要由多级域名组成。比如我的个人博客blog.icexmoon.xyz
,其中xyz
为顶级域名,通常由国家进行管理,比如tv
就是某个非洲小国的域名。icexmoon.xyz
是二级域名,是需要向顶级域名管理机构申请的个人域名,申请成功后可以在二级域名下创建子域名进行使用。比如blog.icexmoon.xyz
就是一个我自己定义的三级域名,用于我的博客。 -
资源路径:示例中
/specials/saw-blade.gif
这部分。通常资源路径对应着服务器上部署的主站目录下的路径,但http service
通常也支持路径重写之类的功能,比如Apache
就可以通过设置route-rewrite
来实现伪静态的URL。
URN
URN全称Uniform Resource Name(统一资源名),它可以在因特网上唯一地定位特定内容的资源。与URL的区别是URN是服务器无关的,也就是说如果同一篇文章存在于多台Web服务器上时,通过URN访问时会自动选取某台服务器进行访问。URN只关心资源内容,而不关心提供服务的是哪台服务器。
看上去很棒,和P2P一样,就算某个服务器失联,只要还有一台服务器提供同样的资源,URN链接就不会失效。但问题是这种技术需要额外的服务器来支持,比如记录哪些服务器上有该资源等。
URN的实际例子类似于这样:urn:isbn:0-486-27557-4
,这个例子是使用urn
唯一定位了一本ISBN为0-486-27557-4
的书。
实际上我惊奇地发现几乎经常使用的磁力链中也有URN的身影:
magnet:?xt=urn:btih:b2f8a751cbf7c31e529af53dfabbe554823d9a1d
。
无论如何,URN并没有在互联网中大范围地推广与使用。
事务
我们将一个完整的HTTP请求-响应过程称为“HTTP事务”:
图源:《HTTP权威指南》
HTTP方法
HTTP协议中根据使用场景的不同,定义了几种HTTP方法(HTTP method):
-
GET:从服务器获取资源
-
POST:发送数据到服务器
-
PUT:向服务器存储数据
-
DELETE:从服务器删除数据
-
HEAD:只返回HTTP报文头
虽然HTTP规定了HTTP方法的使用场景,但在实际应用中,绝大多数网站只使用GET和POST两种方法,并且由前者实现绝大多数请求,后者只会用于表单提交等敏感信息的请求和处理。
只使用GET请求的情况下,可以通过URL参数来实现对“请求动作”的区分,比如:
http://myweb.com/index.php?action=delete&student=123
这个URL可以用于表示一个删除学生数据的HTTP请求。
当然使用GET、POST、PUT、DELETE这全部四种HTTP方法的项目也有,通常见于基于接口的前后端分离的Web项目。
图源:
状态码
HTTP响应报文(Response Message)中会包含一个表示HTTP事务结果的状态码,常见的状态码有:
-
200
:success,成功。 -
302
:Redirect,资源重定向。 -
404
:Not Found,资源没找到。
事实上HTTP状态码通过第一位数字区分不同类型的状态:
-
2XX
:成功 -
3XX
:重定向 -
4XX
:客户端错误 -
5xx
:服务端错误
通常我们需要关注的是
4XX
和5xx
。一开始我很不理解为什么404
是客户端错误,后来想明白了,服务端没有那个页面你客户端一定要请求,可不就是客户端错误嘛。5xx
的服务端错误一般常见的是程序bug,比如PHP直接报错中断执行,就会返回一个类似5xx
的状态码。
更多HTTP状态码见。
此外,HTTP状态码还通常会附加一个说明文字,比如:
-
200 OK
-
200 Success
-
200 Document attached
不同的服务器返回的状态说明文字可能不同,但仅起到一个解释说明的作用,并不会影响HTTP客户端对返回报文的处理逻辑。
Web页面中可以包含多个对象
这点应该很好理解,虽然我们使用URL访问某个页面仅会返回一个HTML文本,但是该文本上可能包含多种资源,比如图片、视频、音频等等:
图源:《HTTP权威指南》
所有这些额外资源都会通过随后的多次HTTP事务获取,并在本地浏览器中完成最终的网页渲染。
报文
HTTP报文由纯文本构成,而非二进制:
图源:《HTTP权威指南》
像上图展示的那样,HTTP报文主要分为三部分:
-
起始行
位于报文第一行。请求报文中会包含HTTP方法、资源路径、HTTP协议版本等信息。响应报文中包含HTTP协议、状态码等信息。
-
报文头(Message Head)
位于起始行下一行。以“键值对”的方式出现(
:
分隔),这里定义了所有的HTTP功能相关的选项,比如是否使用数据压缩节省带宽、使用何种压缩技术、是否使用长连接等。报文头以一个空白行结束。 -
报文体(Message Body)
请求和响应报文中附加的数据都以报文体的方式传输,虽然HTTP报文本身是纯文本,但报文体可以用于传输二进制数据,比如图片等二进制文件。
连接
HTTP依托TCP(Transmission Control Protocol,传输控制协议)连接来完成客户端到服务端的报文传输。
TCP/IP
TCP协议的优点有:
-
无差错数据传输(有校验数据提供数据校验)
-
按序传输(数据以发送的顺序抵达)
-
未分段数据流(可发送任意长度的数据,不浪费带宽)
互联网的七层协议如下图所示:
图源:
连接、IP和端口号
一个HTTP事务的步骤通常是:
-
通过DNS解析获取服务端的IP。
-
创建从客户端到服务端的TCP连接。
-
通过TCP连接发送请求报文到服务端。
-
服务端处理后返回响应报文到客户端。
-
客户端收到报文后关闭连接。
这个过程可以用下图表示:
图源:《HTTP权威指南》
其中HTTP连接的创建过程是所谓的“三次握手”,具体过程可以参考。
Web结构组件
之前的介绍中,主要是两个Web组件参与(Web浏览器和Web服务器),事实上Web应用中还存在其他组件:
-
代理
-
缓存
-
网关
-
隧道
-
Agent 代理
代理
代理是客户端与服务端的一个中间节点,位于客户端一侧,主要用于对客户端发送的HTTP请求以及接收的HTTP响应的过滤和处理。通常的用途是企业假设防火墙以保护局域网,或者是个人用户的一些特殊用途。
最近使用的一个小工具就是通过客户端代理实现的,详情可以阅读。
代理的原理可以用下图说明:
图源:《HTTP权威指南》
缓存
缓存也称为Web缓存(Web cache)或代理缓存(proxy cache)。
缓存很好理解,就是将我们最近请求的网络资源就近保存起来,以便在重复请求时不经过服务器,而通过保存的副本直接获取,这样可以节约带宽并缩短响应时间。其原理可以用下图表示:
图源:《HTTP权威指南》
事实上为了性能考虑,整个HTTP架构使用了多层缓存机制,从服务端到专门的缓存加速服务器,再到客户端缓存,层层加码,可以说理想情况下任何一级缓存都可以拦截客户端请求后直接返回所需资源,大大缓解了服务端压力。但缺点是对于实时性内容要求较高的资源就没法通过缓存来实现,比如去12306买火车票...
网关
网关(gateway)是一种特殊服务器,作为其他服务器的中间实体使用。通常用于HTTP到其它协议的转发:
这种概念更类似于设计模式中的“适配器”,详情见。
隧道
隧道(tunnel)建立后会在客户端与服务端之间形成两条以隧道服务相连接的路径,并对客户端和服务端之间的往来数据进行“盲转发”。其工作过程可以用下图表示:
这里展示的是一种SSL隧道,客户端先使用SSL客户端将请求报文加密,然后作为报文体传输给服务端的80端口,服务端的SSL模块再进行解密,以获取真实的请求报文,再转交给443端口监听的服务进行处理。通过这种方式可以实现一个仅对外提供80端口服务的具有SSL安全特性的Web服务(虽然似乎以现在的眼光看来并没有什么卵用,因为现在的浏览器已经很激进地在给不支持HTTPS的网站标记为不安全了,但可能2000年时候很难想象吧)。
可能天朝人知道的更广泛的隧道的使用用途就是“梯子”了。
Agent代理
用户Agent代理(User Agent)是指代替用户发起HTTP请求的客户端程序,通常来说就是各种网页浏览器,也包括各种爬虫程序或者机器人程序。
下面是一个爬虫程序的图示:
图源:《HTTP权威指南》
如果你使用浏览器的开发者工具(F12)就能在请求报文头中找到:
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
这个头信息就是说明发送请求报文的浏览器的相关信息,服务端可以使用该信息来分析请求情况,或者甄别爬虫程序和自动化脚本,当然爬虫程序和自动化脚本也可以使用该信息伪装成普通的浏览器。
文章评论