HTTP首部解析

2,694 阅读17分钟

转载请注明出处:

  1. HTTP首部解析:博客园
  2. HTTP首部字段:知乎

文章目录

1.与HTTP协议相关的Web服务器

2.HTTP首部


与HTTP协议相关的Web服务器

在说明HTTP首部相关知识之前,有必要先了解一下与HTTP协作的Web服务器。

用一台主机实现多个域名

HTTP/1.1规范明确提出,允许一台Web服务器实现多个域名。即使物理层面上只有一台服务器,但只要使用虚拟主机(又称虚拟服务器)的功能,就可以假想已经具有多台服务器。

虚拟主机,又可以叫做虚拟服务器,是一种在单一主机获主机群上,实现多网域服务的方法,可以运行多个网站或服务的技术。具体内容可参考wiki。传送门:wiki: 虚拟主机

但是在同一台服务器上部署多个网站域名会有一个问题,因为只有一台物理服务器,意味着只有一个IP地址,在DNS服务将域名解析成IP地址之后,在收到请求之后就需要弄清楚究竟要访问哪个域名。

这个问题其实有两种方法可以解决。一是在发送请求时必须请求头部字段中增加Host字段,表明请求的主机名。二是在一台服务器上使用不同的IP地址来管理多个服务。

通信数据转发程序:代理

代理服务器位于服务器和客户端之间,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。前端工程师常用的抓包软件Fiddler、Charles就是通过代理来实现抓包的。

代理服务器的基本行为就是接收客户端发送的请求后转发给服务器,代理不改变请求URI,会直接发送给前方具有资源的目标服务器。持有资源实体的服务器称为源服务器,从源服务器返回的响应经过代理服务器后再传给客户端。每经过一次代理服务器,都会追加Via首部字段信息,表明经过的代理服务器信息。要不然都不知道谁跟谁了...

总的来说呢,使用代理服务器有以下好处

1.利用缓存技术减少服务器网络带宽流量的消耗

2.针对特定网站的访问控制(控制哪些站点可以访问服务器,哪些不能访问,实现访问过滤功能)

代理有多种使用方法,按照两种基准分类,一种是是否缓存(缓存代理),另一种是是否会修改报文(透明代理)。详细资料可参见wiki。传送门:wiki: 代理服务器

保存资源的缓存

上面所说的缓存技术是指代理服务器或客户端本地磁盘内保存的资源副本。利用缓存可以减少对源服务器的访问(从代理服务器或浏览器读取未过期的缓存资源),因此也就节省了通信流量和通信时间了。

缓存(代理)服务器的优势在于利用缓存可避免多次从源服务器请求资源。因此客户端可就近从浏览器或代理服务器上获取资源,而源服务器也不必多次处理相同的请求了。

但是不管是浏览器或者是代理服务器上缓存的资源,都存在缓存过期的情况。如果缓存未过期,那么就可以直接读取缓存资源;如果缓存过期了,代理服务器将会再次从源服务器上获取更新之后的资源。而浏览器并不会马上发起一个请求给服务器,而是会发起一个条件GET请求(If-Modified-Since和Last-Modified字段)。

稍微总结一下。

1.一台Web服务器可以配置多个域名,在请求时需要添加Host字段表示请求的主机名或者是多个IP管理不同的服务。

2.代理服务器的基本行为是将客户端发送的请求转发给服务器,然后直接将请求资源直接转发给源服务器。可以利用代理服务器或者浏览器对响应进行缓存,减少同一请求对源服务器的访问所产生的带宽资源的浪费。

HTTP首部

请求头和响应头共有的首部字段包括:通用首部字段、实体首部字段、其他首部字段。而请求头特有的首部字段是请求首部字段,响应头特有的首部字段是响应首部字段。以下是HTTP/1.1定义了47种首部字段。

以下就简单的说明一下每一个字段。

HTTP/1.1通用首部字段

通用首部字段是指,请求报文和响应报文双方都会使用的首部。

Cache-Control指令:

能够控制缓存的工作行为。指令的参数是可选的,多个指令之间通过','分隔。Cache-Control指令可用于请求和响应时。

public: 缓存响应指令。明确表明其他用户也可以利用缓存。

private: 缓存响应指令。表示响应只以特定的用户作为对象,代理服务器只会对特定用户提供缓存资源,对于其他用户发送过去来的请求,代理服务器则不会返回缓存。

no-cache: 目的是为了防止从缓存中返回过期的资源。客户端发送的请求如果包含no-cache指令,表示客户端将不会接收缓存过的响应。于是,代理服务器必须把客户端请求转发给源服务器。如果服务器返回的响应中包含no-cache指令,那么代理服务器不能对资源进行缓存。源服务器以后也将不再对代理服务器请求中提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。

no-store: 禁止代理服务器缓存响应资源。

s-maxage: 表示处于公共代理服务器情况下缓存过期没有超过指定时间时,就会返回缓存。对于向同一个用户重复返回响应的服务器来说,这个指令没有任何作用。另外呢,当使用s-maxage指令后,则直接忽略对Expires首部字段及max-age指令的处理。例如Cache-Control: s-maxage=600(秒)表示公共代理服务器中缓存过期没超过10分钟则可以返回缓存资源。

max-age: 形式为Cache-Control: max-age=600(秒)。如果客户端发送的请求中包含max-age指令时,表示缓存过期没超过指定的时间,那么客户端就接收缓存的资源。如果max-age值为0,表示代理服务器需要将请求转发给源服务器。

当源服务器返回的响应中包含max-age指令时,代理服务器将不对资源的有效性进行确认,而max-age数值代表资源保存为缓存的最长时间。

在HTTP/1.1版本的代理服务器遇到同时存在Expires字段的情况下,会优先处理max-age指令而忽略掉Expires字段。

min-fresh: 要求代理服务器返回至少还没有超过指定时间的缓存资源。如Cache-Control: min-fresh=60(秒)当指定min-fresh为60秒后,60秒内的响应可以返回,而超过60秒的响应就无法返回了。

max-stale: 表示缓存过期在指定时间内,客户仍然会接收。如果未指定任何参数值,那么无论经过多久,客户端都会接受响应。

only-if-cached: 表示客户端仅在代理服务器本地缓存目标资源的情况下才会要求其返回。也就是说,该指令会要求代理服务器不重新加载响应,也不会再次确认资源的有效性。若发生请求代理服务器的本地缓存无响应,则返回状态码504 Gateway Timeout

must-revalidate: 表示代理服务器会向源服务器再次验证即将返回的响应缓存是否仍然有效。如果代理无法连通源服务器再次获取有效资源的话,代理服务器会给客户端返回504(Gateway Timeout)状态码。另外会忽略请求的max-stale指令。

proxy-revalidate: 要求代理服务器对缓存的响应有效性再进行验证。

no-transform: 无论是在请求中还是在响应头中,缓存都不能改变实体主体的媒体类型。

Connection

Connection字段具有以下两个作用

控制不再转发给代理服务器的首部字段: 格式如下Connection: 不再转发的首部字段名。在客户端发送请求和服务器返回响应内,使用Connection字段可以控制不在转发给代理服务器

持久连接:Connection: keep-alive。HTTP/1.1版本默认连接是持久连接。客户端和服务器只需建立一次TCP连接,就可以相互进行多次HTTP通信了。直到有一方明确表示需要断开TCP连接,持久连接才会结束。

Pragma

该首部字段仅作为与HTTP/1.0的向后兼容而定义。形式如下Pragma: no-cache。只用在响应头中,表示代理服务器不能对响应进行缓存。

pargma首部字段与no-cache指令作用相同,但是为了兼容HTTP协议版本的问题,HTTP响应头中会同时含有下面两个字段。

Trailer

Trailer字段会事先说明在报文主体后记录了哪些首部字段。主要用于HTTP/1.1版本的分块传输编码时。

Transfer-Encoding

Transfer-Encoding字段规定了传输报文主体时采用的编码方式,仅对分块传输编码有效。

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: keep-alive
cfo             <--16进制(10进制为3312)
·····3312字节分块数据·····
392             <--16进制(10进制为914)
·····914字节分块数据······

以上例子中,Transfer-Encoding字段值有效使用分块传输编码,且被分成了3312字节和914字节大小的分块数据。

Upgrade

Upgrade字段检测HTTP协议及其他协议是否可以使用更高的版本进行通信。如在使用WebSocket协议时会使用到此字段,在HTTP通信过程中,会使用HTTP升级将HTTP协议升级为WebSocket协议。之后服务器端返回101 Switching Protocols状态码表示协议转换成功,此时就可以使用WebSocket协议进行全双工双向通信了。对WebSocket不熟悉的朋友可以参考这篇文章。传送门:WebSocket协议解析

Via

Via字段的目的是为了追踪客户端与服务器之间的请求和响应报文的传输路径。报文在经过代理服务器或网关时,会在Via字段中附加自身服务器的信息,然后再进行转发。通常Via字段会与Max-Forwards字段配合使用。对Max-Forwards字段的解释请看这篇文章。传送门: Max-Forwards

请求首部字段

Accept

Accept字段可以通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可以使用type/subtype这种形式,一次指定多种媒体类型,通过q=来给媒体类型增加优先级,最大为1.0, 最小为0,默认值为1.0

Accept:q=1.0 application/json; q=0.8 text/plain; q=0.7 */*

Accept-Charset

Accept-Charset字段用来通知服务器用户代理支持的字符集及字符集的相对优先顺序。另外,可一次性指定多种字符集。与Accept字段相同的是可用权重q值来表示相对优先级。

Accept-Encoding

Accept-Encoding字段用来通知服务器用户代理支持的内容编码及内容编码的相对优先级。内容编码包括gzip、compress、deflate、identity(不执行压缩的默认编码格式)等。

Accept-Language

Accept-Language用来告知服务器用户代理能够处理的自然语言集(中文或者英文), 以及自然语言集的相对优先级,可一次性指定多种自然语言集

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

Authorization

Authorization字段用来告知服务器,用户代理的认证信息(证书)。通常想要通过服务器认证的用户代理会在接收到返回的401状态码响应后,把字段Authorization加入请求中。

Host

Host字段会告知服务器请求的资源所处的互联网主机名和端口号。请求被发送到服务器时,会使用DNS服务将域名解析成IP地址。如果此时相同的IP地址下部署了多个域名(虚拟主机),那么服务器就无法理解究竟是哪个域名对应的请求。因此就需要使用Host字段来明确指出请求的主机名。

If-None-Match If-None-Match字段与Etag配合使用,当与Etag字段值不一致时,服务器会处理请求。如果一致,则服务器端会返回304 Not Modified。

在典型的用法中,当一个URL被请求,Web服务器会返回资源和其对应的Etag值,会被放置在HTTP响应头中。

Etag: "686897696a7c876b7e"

然后,客户端可以决定是否缓存这个资源和Etag。以后,如果客户端想再次请求相同的url,将会发送一个包含已保存的Etag和If-None-Match字段的请求。

If-None-Match: "686897696a7c876b7e"

客户端请求之后,服务器可能会比较客户端的Etag和当前版本资源的ETag。如果ETag值匹配,这就意味着资源没有改变,服务器便会发送回一个极短的响应,包含HTTP “304 Not Modified”的状态。304状态告诉客户端,它的缓存版本是最新的,并应该使用它。 然而,如果ETag的值不匹配,这就意味着资源很可能发生了变化,那么,一个完整的响应(200 OK)就会被返回,包括资源的内容,就好像ETag没有被使用。这种情况下,客户端可以用新返回的资源和新的ETag替代先前的缓存版本。

If-Modified-Since

If-Modified-Since字段与响应头的Last-Modified字段匹配使用。当Last-Modified字段值的时间在其之后,表示资源发生了更新,则服务器会返回200 OK的状态码,当Last-Modified字段值的时间在其之前,表明资源没有发生更新,则服务器会返回304 Not Modified状态码。当与If-None-Match字段联合使用的时候,If-Modified-Since字段会被忽略,除非服务器不支持If-None-Match字段。If-Modified-Since用于确认代理服务器或客户端拥有的本地资源的有效性。

If-Range

If-Range字段会告知服务器若指定的If-Range字段值和请求资源的Etag值获时间相一致,则作为范围请求处理,返回的响应头会包含Content-Range字段,表示返回的范围字节数。反之,则返回全体资源。此字段会与Range字段配合使用。

Proxy-Authorization

Proxy-Authorization: Basic dFDGADdjgjadfDSFJ5

接收到代理服务器发送过来的认证信息之后,客户端会发送包含该首部字段的请求,以告知服务器认证所需要的信息。

Referer

Referer字段会告知服务器请求的原始资源的URI。

响应首部字段

Accept-Ranges

Accpet-Ranges字段用来告知客户端服务器能否处理范围请求,以指定获取服务器端某个部分的资源。可指定的字段值有两种,可处理范围请求时指定其为bytes,反之指定为none。

ETag

服务器会为每份资源分配对应的ETag值,当资源更新时,ETag值也需要更新。ETag字段通常与If-None-Match字段配合使用。当ETag值与If-None-Match值相互匹配时,表示请求的资源没有发生变化,则服务器会返回304 Not Modified状态码;如果相互不匹配,则会返回200 OK状态码。另外,ETag分为强ETag和弱ETag,它们通过ETag标识符的开头是否存在“W/”来区分,如

"123456789"   -- 一个强ETag验证符
W/"123456789"  -- 一个弱ETag验证符

具体的区别可参考wiki。传送门: HTTP ETag

Proxy-Authenticate && WWW-Authenticate Proxy-Authenticate字段会把有代理服务器所要求的认证信息发送给客户端,通常与Proxy-Authorization字段配合使用。

WWW-Authenticate字段用于HTTP访问认证。通常与Authorization字段配合使用。

实体首部字段

实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。 Allow

形式如Allow: GET, POST。Allow字段用于通知客户端能够支持的HTTP方法。当服务器接收到不支持的HTTP方法时,会以状态码405 Method Not Allowed作为响应返回。

Content-Encoding

该字段会告知客户端服务器对实体的主体部分选用的内容编码方式。主要采用4种内容编码方式:gzip、compress、deflate、identity。

Content-Language && Content-Length

Content-Language告知客户端实体主体采用的自然语言集。Content-Length告知客户端实体主体的大小。

Content-Range && Content-Type

Content-Range告知客户端响应返回的实体的哪个部分符合范围请求,该字段针对范围请求。字段值以字节为单位,表示当前发送部分及整个实体大小。形式如Content-Range: bytes 5001-10000/10000

Content-Type告知客户端实体主体采用的媒体类型,媒体类型与Accept字段相同。

Expries

Expries字段用于告知客户端资源的过期时间。如果是代理服务器接收到带有Expires字段的响应时,会将资源缓存起来。当请求相同资源且未超过指定时间时,会返回缓存的资源。当超过指定时间后,代理服务器会将请求转发给源服务器。如果不希望代理服务器对资源进行缓存时,可以将Expires字段设置成与Date字段的值相同。在浏览器方面,当请求的资源过期时,不会立马向源服务器发起请求,而是会先发起条件请求(If-Modified-Since与Last-Modifed字段)。

当Expires字段遇上Cache-Control字段的max-age指令时,会优先处理max-age指令。

为Cookie服务的字段

由于HTTP是无状态协议,因此需要Cookie结合HTTP来实现用户的状态管理。对于Cookie的说明可以看这篇文章。传送门:前端存储方案


参考资料

1.《图解HTTP》

2.MDN web docs

3.维基百科