HTTP指南

254 阅读18分钟

内容都总结自《HTTP权威指南》,对其中的部分知识点进行了总结概括。会持续更新,敬请期待~~

一、HTTP概述

1.1 媒体类型(MIME type)

因特网上有数千种不同的数据类型,HTTP仔细地给每种要通过Web传输的对象都打上了MIME(Multipurpose Internet Mail Extension)类型的数据格式标签。最初是用在电子邮件系统,后HTTP也采纳了它。

当Web浏览器从服务器中取回一个对象时,会去查看相关的MIME类型,看看是否知道应该如何处理这个对象。大多数浏览器可以处理百种常见的对象类型:显示图片文件、解析并格式化HTML文件、通过计算机声卡播放音频文件、运行外部插件软件来处理特殊格式数据等。

MIME类型是一种文本标记,表示一种主要的对象类型和一个特定的子类型,中间用斜杆分隔,放在Http的Response Headerscontent-type 字段。常见的主要的对象类型有:

  • application/*

描述了很多应用程序特有的MIME类型

  1. application/x-javascript: Javascript文件
  2. application/json: XHR请求或者Json文件
  3. application/octet-stream: 未分类的二进制数据,比如一些font字体的传输,还有很长的视频的分段传输都有用到这个content type
  4. application/x-www-form-urlencoded:form表单的简单请求,数据被编码成以&分割的键=值对,不支持二进制数据,(应使用 multipart/form-data 代替)
  • text/*

包含了字符和潜在的格式转化信息

  1. text/css: css文件
  2. text/html: html文件
  3. text/plain: 普通的文本
  • video/*

视频电影格式。注意,有些视频格式被划分为application类型。

  1. video/quicktime: 苹果Quicktime的视频格式
  • image/*

图片

  1. image/png: PNG编码图片
  2. image/webp: chrome和opera支持的WEBP格式图片
  • multipart/*

是包含有其他对象的组合对象。子类型描述了多部分封装的实现,以及如何处理组件。

  1. multipart/form-data: 根据用户填表的结果将一组值封装
  • model/*

是IETF注册的扩展类型。他表示物理世界的数学模型,用于计算机辅助设计和三维图像。

  1. model/vnd.dwf: DWF CAD文件
  • binary/*

二进制格式

  1. binary/octet-stream: 有些字体文件
  • message/*

用来(通过电子邮件、HTTP、或其他传输协议)交互数据对象的复合类型

  1. message/s-http: 安全HTTP报文,是对SSL上的HTTP的替代方式
  2. message/rfc822: 完整的电子邮件报文
  • audio/*

音频内容文件

  1. audio/x-wav:WAV音频文件
  2. audio/mp4: mp4格式音频文件

web的结构组件

1.2 代理

Web代理(proxy)服务器是网络的中间实体,位于客户端和服务器之间,接收所有客户端的HTTP请求,并将这些请求转发给服务器(可能会对请求进行修改之后转发)。

出于安全考虑,通常会将代理作为转发所有Web流量的可信任中间节点使用。代理还可以对请求和响应进行过滤。比如,对小学生屏蔽一些成人才能看的内容。

1.2.1 代理与网关对比

严格来说,代理连接的是两个或多个使用相同协议的应用程序,而网关连接的则是两个或多个使用不同协议的端点。

HTTP/HTTP代理

graph LR
HTTP客户端a -->|HTTP| Web代理
Web代理 -->|HTTP| WEB服务器

Web代理 -->|HTTP| HTTP客户端a
WEB服务器 -->|HTTP| Web代理

HTTP/POP网关,把HTTP的前台与POP E-mail的后端连接起来,让用户可以通过HTTP读取E-mail了。基于Web的E-mail程序,如Yahoo!邮箱都是HTTP E-mail网关。

graph LR
HTTP客户端b -->|HTTP| HTTP/E-mail网关
HTTP/E-mail网关 -->|POP| E-mail服务器

HTTP/E-mail网关 -->|HTTP| HTTP客户端b
E-mail服务器 -->|POP| HTTP/E-mail网关

但实际上,代理和网关之间的区别很模糊。由于浏览器和服务器实现的是不同版本的HTTP,代理也经常要做一些协议转换工作。而商业化的代理服务器也会实现网关的功能来支持SSL安全协议、SOCKS防火墙、FTP访问,以及基于Web的应用程序。

1.2.2 代理服务器的部署方式

  • 出口代理 可以将代理固定在本地网络的出口点,以便控制本地网络与大型因特网之间的流量。比如,公司网络中使用出口代理,提供针对公司外部恶意黑客的防火墙保护,降低带宽费用,提高因特网流量的性能。小学使用出口代理防止早熟学生浏览不恰当的内容。

私有LAN的出口代理

graph LR
客户端 -->|本地网络| 出口代理服务器
出口代理服务器 -->|因特网| Web服务器

出口代理服务器 -->|本地网络| 客户端
Web服务器 -->|因特网| 出口代理服务器
  • 访问代理 代理经常被放在ISP(互联网服务提供商)访问点上,用以处理来自客户的聚合请求。ISP使用缓存代理来存储常用文档的副本,以提高用户(尤其是高速连接用户)的下载速度,降低因特网带宽耗费。

  • 反向代理 反向代理服务器通常会被部署在网络边缘,在Web服务器之前,与出口代理服务器正好在一个对位上。可以提高Web服务器的安全特性,做负载均衡等。例如我们经常用到的nginx。

graph LR
客户端 -->|因特网| 反向代理服务器
反向代理服务器 -->|本地网络| Web服务器

反向代理服务器 -->|因特网| 客户端
Web服务器 -->|本地网络| 反向代理服务器
  • 网络交换代理 可以将具有足够处理能力的代理放在网络之间的因特网对等交换点上,通过缓存来减轻因特网节点的拥塞,并对流量进行监控。

1.2.3 代理的层次结构

现实生活中的代理,大多都是以上几种的代理方式的组合。

代理层级结构中,代理服务器被赋予了父子关系。靠近服务器的被称为父代理,靠近客户端的被称为子代理,并且子代理还会动态选择父代理。

  • 负载均衡:子代理根据父代理工作负载级别决定选择父代理
  • 地理位置附近路由:子代理可能会选择负责原始服务器所在的物理区的父代理
  • 协议/类型路由:子代理可能会根据URI将报文转发到不同的父代理和原始服务器上。比如对特定类型图片,访问代理将请求转发给一个特定的压缩器代理,然后对图片进行压缩。
  • 基于订购的路由:比如发布者为高性能服务额外付费,他们的URI就会被转发到大型的缓存或压缩引擎上去,以提高性能。

不同的产品中,动态父路由逻辑的实现方式各有不同,包括使用配置文件、脚本语言和动态可执行插件等。

1.2.4 客户端的代理设置

  • 手工配置:很多web客户端都允许用户手工配置代理。
  • 客户端代理配置:PAC文件,如下图,在自动代理配置框中提供一个URI,浏览器会从这个URI上获取PAC文件,并执行PAC文件必须定义的FindProxyForURL函数,来使用适当的代理服务器。
function FindProxyForURL(url, host) {
  if (defaultMatcher.matchesAny(url, host) instanceof BlockingFilter) {
    return proxy; // 使用指定的代理
  }
  return direct; // 不经过任何代理,直接进行连接
}

chrome-高级设置-可打开计算机网络设置代理

截屏2021-05-02 下午1.23.24.png

截屏2021-05-02 下午1.24.31.png

1.2.5 URI的客户端自动扩展和主机名解析

比如,我们在搜索百度时,输入baidu.com,为什么浏览器会补全www.baidu.com 呢? 这是因为,在没有找到主机时,浏览器会尝试着提供某种主机名自动扩展机制,尝试加入前缀www. 和后缀 .com ,且大多数DNS配置会根据用户输入前缀,自动搜索域名。

1.2.6 追踪报文

现在,在将Web请求从客户端传送到服务器的路径上,经过多个代理是很常见的。

via首部字段列出了与报文途径的每个中间节点(代理或网关)有关的信息。报文每经过一个节点,都必须将这个中间节点添加到via列表的末尾。如下例子:

// Response Headers
server: Tengine // 对原始服务器使用的软件进行了描述
via: cache45.l2cn1803[0,304-0,H], cache17.l2cn1803[1,0], cache13.cn747[0,0,200-0,H], cache6.cn747[5,0]

每个Via路标中最多包含四个组件:一个可选的协议名(默认HTTP)、一个必选的协议版本、一个必选的节点名称和一个可选的描述注释

注意,server是用于原始服务器的,代理应添加的是via条目。

1.3 缓存

Web缓存(Web cache)或代理缓存(proxy cache)是一种特殊的HTTP代理服务器,可以将经过代理传送的常用文档复制保存起来。

1.4 网关

网关(gateway)是一种特殊的服务器,作为其他服务器的中间实体。通常用于将HTTP流量转换成其他的协议。

例如,一个HTTP/FTP网关会通过HTTP请求接收对FTP URI的请求,但通过FTP协议来获取文档。

graph LR
HTTP客户端 -->|HTTP| HTTP/FTP网关
HTTP/FTP网关 -->|FTP| FTP服务器

HTTP/FTP网关 -->|HTTP| HTTP客户端
FTP服务器 -->|FTP| HTTP/FTP网关

1.5 隧道

隧道(tunnel)是建立起来之后,就会在两条连接之间对原始数据进行盲转发的HTTP应用程序。HTTP隧道的一种常见用途就是通过HTTP连接承载加密的安全套接字层(SSL,Secure Sockets Layer)流量,这样SSL流量就可以穿过只允许Web流量通过的防火墙了。

1.6 Agent代理

用户Agent代理是代表用户发起HTTP请求的客户端程序。如:web浏览器、爬虫等。

HTTPS

HTTPS是最流行的HTTP安全形式。它是由网景公司首创的,所有主要浏览器和服务器都支持此协议。使用HTTPS时,所有的HTTP请求和响应数据在发送到网络之前,都要进行加密。HTTPS在HTTP下面提供了一个传输级的密码安全层--可以使用SSL,也可以使用其后继者--传输层安全(Transport Layer Security, TLS)。

  • HTTP
graph TD
HTTP --> TCP
TCP --> IP
IP --> 网络接口
  • HTTPS

大部分困难的编码及解码工作都是在SSL库中完成的,所以Web客户端和服务器在HTTP的基础上,用SSL的输入/输出调用取代TCP的调用,再增加其他几个调用来配置和管理安全信息就行了。

graph TD
HTTP --> SSL
SSL --> TCP
TCP --> IP
IP --> 网络接口

数字加密基本概念介绍

  • 密码:对文本进行编码,使偷窥者无法识别的算法
  • 密钥:改变密码行为的数字化参数
  • 对称密钥加密系统: 编/解码使用相同的密钥的算法
  • 非对称密钥加密系统:编/解码使用不同密钥的算法
  • 公开密钥加密技术:公开密钥加密技术没有为每对主机使用单独的加密/解密密钥,而是使用了两个非对称密钥:一个用来对主机报文编码,一个用来对主机报文解码。编码密钥是众所周知的,但是只有主机才知道私有的解密密钥。每个客户端都可以用同一个密钥对发给服务器的报文进行编码,但除了服务器,没有其他人能对报文进行解码,因为只有服务器才有解码的私钥。
  • RSA:所有公开密钥非对称加密系统所面临的共同挑战是,要确保即便有人拥有了下面所有线索,也无法计算出保密的私钥:(1)公钥(2)一小片拦截下来的密文(3)一条报文以及与之相关的密文。RSA算法就是满足了所有这些条件的流行的公开密钥加密系统,它是在MIT发明的,后来由RSA数据安全公司将其商业化。
  • 混合加密系统和会话密钥:公开密钥加密算法的计算可能会很慢。HTTPS采用的是对称加密与非对称加密结合的混合加密算法。步骤如下:(1)浏览器在获取到服务器的公钥后,生成一个临时的随机的对称密钥,然后用这个对称密钥对报文进行加密,然后用获得的服务器公钥加密这个临时的对称密钥。再把这些信息传给服务器。(2)服务器获得信息后,用自己的私钥解密浏览器加密的对称密钥,然后,用得到的对称密钥解密报文,用对称密钥加密要回传的报文信息。 这样,就可以通过更快的对称加密技术对其余的数据进行加密,非对称加密技术其实只加密了浏览器随机生成的对称密钥(会话密钥)而已。

HTTPS加密流程步骤总结

  1. 服务器把它的证书告诉客户端,证书内容里带着公钥(其实前面还有一步是客户端告诉服务器会啥加密算法);
  2. 客户端检验证书是否有效;
  3. 客户端生成一个随机的对称加密密钥(注意这个密钥是对称加密的啊),用第一步里的公钥对它加密;
  4. 客户端把第三步的结果告诉服务器(一并的还有要传输的数据,即 HTTP 请求,当然也是被对称加密过的);
  5. 服务器收到以后用私钥解开得到第三步传过来的对称加密密钥,并用它解密传输过来的数据;
  6. 服务器处理这些数据后,把要传给客户端的数据(即 HTTP 响应)还是用对称加密密钥加密后再传;
  7. 客户端收到后用对称加密密钥解密。
  8. 重复 4-7 步骤。
  • 数字签名:用来验证报文未被伪造或篡改的校验和
  • 数字证书:由一个可信的组织验证和签发的识别信息 点击浏览器网址导航栏左边的小锁🔒,就可以看见这个网站的证书。我截图的是阿里云的SSL证书。如何购买证书,如何创建私钥,大家可以去看一下阿里云SSL证书证书服务的产品介绍,也会对这些概念有更直观的理解。

截屏2021-05-05 上午11.41.12.png

  • 站点证书有效性:SSL自身不要求用户检查Web服务器证书,但大部分现代浏览器都会对证书进行简单的完整性检查,并为用户提供进一步彻查的手段,步骤如下:(1)日期检测(2)签名颁发者可信度检测(3)签名检测(4)站点身份检测

建立安全传输

在未加密的HTTP中,客户端会打开一条到Web服务器端口80的TCP连接。在HTTPS中,客户端首先打开一条到Web服务器端口443的连接。一旦建立了TCP连接,客户端和服务器就会初始化SSL层,进行一次SSL握手:

  1. 交换协议版本号
  2. 选择一个两端都了解的密码
  3. 对两端的身份进行认证
  4. 生成临时的会话密钥

通过代理以隧道形式传输安全流量

只要客户端开始使用服务器的公开密钥对发往服务器的数据进行加密,代理就再也不能读取HTTP首部了! 代理不能读取HTTP首部,就无法知道应该将请求转向何处了。为了使HTTPS与代理配合工作,要进行几处修改以告知代理连接到何处。一种常用的技术就是HTTPS SSL 隧道协议。使用HTTPS隧道协议,客户端首先要告知代理,它想要连接的安全主机和端口。这是在开始加密之前,以明文形式告知的,所以代理可以理解这条信息。

HTTP通过新的名为CONNECT的扩展方法来发送明文形式的端点信息。CONNECT方法会告诉代理,打开一条到所期望主机和端口号的连接。这项工作完成之后,直接在客户端和服务器之间以隧道的形式传输数据。

CONNECT home.netscape.com:443 HTTP/1.1
User-agent:Mozilla/5.0

<raw SSL-encrypted data would fllow here ...>

在请求中的空行之后,客户端会等待来自代理的响应。代理会对请求进行评估,确保它是有效的,而且用户有权请求这样一条连接。如果一切正常,代理会建立一条到目标服务器的连接。如果成功,就向客户端发送一条200 Connection Established 响应。

HTTP请求实体

HTTP1.1定义了以下十个基本的HTTP头实体:

  • Content-Type:实体中所承载的对象类型
  • Content-Length:所传送的实体主体的长度或大小。持久连接必须要Content-Length来判断一条报文的结束与开始。
  • Content-Language:所传送的实体对象最匹配的人类语言
  • Content-Encoding:对象数据所做的任意变换(比如,压缩),有gzip、compress、deflate、br、identity(表明没有对实体进行编码)。目前,gzip是效率最高的。
  • Content-Location:一个备用位置,请求时可通过它获得对象
  • Content-Range:如果是范围请求,这个首部说明它是整体的哪个部分
  • Content-MD5:实体主体内容的校验和
  • Last-Modified:所传输的内容在服务器上创建或最后修改的时间
  • Expires:实体数据将要失效的日期时间
  • Allow:该资源允许请求的方法
  • Etag:实体的位置验证码
  • Cache-Control:指出该如何缓存该文档

为了提升请求效率,服务器上的源文件可以被缓存在CDN、NG、浏览器上面,因此可以设置缓存策略来,优化资源请求。

此处涉及到资源缓存何时更新的问题,需要进行新鲜度验证。服务器可以提供这两个首部之一来提供这些信息:Expires(HTTP1.0)和Cache-Control(HTTP1.1)。在文档还是新鲜的情况下,如果有缓存就会直接拿缓存的资源,此时返回的状态码是200。当新鲜度过期后,就需要验证码来验证是否需要拉去新的资源(此时状态码是200),还是继续使用缓存(此时状态码是304)。

Expires提供的是一个文档过期的绝对时间,是与浏览器时间进行比对的,因此存在浏览器时间不对,导致缓存失效的问题。

expires: Sun, 21 Aug 2022 03:40:05 GMT

Cache-Control提供的是文档过期的相对时间,配合max-age使用,除此之外还有很多指令可用:

指令报文类型描述举例说明
no-cache请求在重新向服务器验证之前,不要返回文档的缓存副本可以看见在chrome浏览器netWork里勾选了Disable Cache选项之后,请求头上就会带上这个参数
no-cache响应可以缓存静态资源,但是每次都要想服务器询问是否有更新资源cache-control:no-cache
no-store请求不要返回文档的缓存副本。不要保存服务器的响应
no-store响应不缓存静态资源,没次都取服务器取
max-age请求缓存中的文档不能超过指定的使用期max-age=31536000
max-age响应单位是秒,指定文档可以被缓存的新鲜度时间。在该时间内,如果有缓存直接取缓存文件,不会询问服务器。超过该时间会去询问服务器,是否有更新max-age=31536000
private响应资源只能被浏览器缓存,不能被缓存服务器缓存
public响应表示资源可以被任何服务器缓存cache-control: public, max-age=3600
must-revalidate响应每次响应都必须先向服务器发起验证Cache-Control: max-age=0, must-revalidate

范围请求

常见的场景有:

  1. 平时下载东西的时候,可能网络不好,下载中断了,但是还可以点击继续下载,这就是范围请求的一种例子。
  2. 还有就是下载一个文件,可以分段从不同的服务器下载资源片段,加速资源下载效率。 与之相关的http请求头字段有:
  • Range: bytes=2323- 表明客户端请求的是文档2323字节之后的部分,不给出结尾字节数,因为请求方可能不知道文档的大小。
  • 不是所有的服务器都支持范围请求,服务器要在响应中包含Accept-Ranges:bytes才行。
  • 对于客户端在一个请求内请求多个不同范围的情况,返回的响应也是单个实体,它有一个多部分主体及Content-Type: multipart/byteranges首部。

拓展阅读