文章目录
介绍
上一篇博文着重介绍了Cache-Control
,这篇博文将会介绍剩余的:
Connection
Date
Transfer-Enconding
Trailer
Upgrade
Via
Warning
1. Connection
Connection
头信息有2个作用,分别是:
- 控制不再转发给代理服务器的头信息
- 管理持久连接
(1).控制不再转发的头信息
Connection:逐跳首部
什么是逐跳首部?参见:这可能是最全的Http头信息资料了
例如:客户端发送给代理服务器的中头信息中是
GET / HTTP/1.1
Connection:Upgrade
Upgrade:HTTP/1.1
Cache-Control:no-cache
那么代理服务器发送给下一个服务器(可能是代理,也可能是最终服务器)的头信息中就会将Upgrade
头信息删除,变成
GET / HTTP/1.1
Cache-Control:no-cache
(2).管理持久连接
<!--关闭连接-->
Connection:close
<!--开启持久连接(适用于Http 1.1之前的版本)-->
Connection:Keep-Alive
在HTTP 1.1
版本中,所有的连接默认都是持久连接
持久连接:进行一次Http通讯后,不断开TCP连接
当明确想断开连接时使用Connection:close
在HTTP 1.1
之前的版本中,默认都是非持久连接,因此如果要保持持久连接需要指定Connection:Keep-Alive
2.Date
Date
指明了创建Http
报文的时间
使用的格式有:
- RFC1123中规定的格式
<!--2021年10月17号,星期天,下午3点08分00秒-->
Date:Sun, 17 Oct 2021 15:08:00 GMT
- RFC850中规定的格式
<!--2021年10月17号,星期天,下午3点08分00秒-->
Date:Sun, 17-Oct-21 15:08:00 GMT
- C语言标准库中
asctime()
的输出格式
<!--2021年10月17号,星期天,下午3点08分00秒-->
Date:Sun Oct 17 15:08:00 2021
3.Transfer-Enconding
该头信息规定了传输报文主体是采用的编码方式。注意和Content-Encoding
区分。
-
Transfer-Enconding
:在传输过程中使用的编码方式,仅用于两个节点之间的传递,而不是资源本身 [1]。例如:源服务器采用了`gzip`传送给了代理服务器,代理服务器解析数据后,将传输方式更改为`chunked`分块传输给客户端
-
Content-Encoding
:报文主体采用什么方式编码,整个传输过程中都不会更改
<!--分块传输-->
Transfer-Enconding:chunked
<!--采用 Lempel-Ziv-Welch (LZW) 压缩算法,这种内容编码方式已经被大部分浏览器弃-->
Transfer-Encoding: compress
<!--采用 zlib 结构 (在 RFC 1950 中规定),和 deflate 压缩算法(在 RFC 1951 中规定)。-->
Transfer-Encoding: deflate
<!--表示采用 Lempel-Ziv coding (LZ77) 压缩算法,以及32位CRC校验的编码方式-->
Transfer-Encoding: gzip
<!--用于指代自身(例如:未经过压缩和修改)。除非特别指明,这个标记始终可以被接受-->
Transfer-Encoding: identity
分块传输会将实体分成多个部分,每一块都会用十六进制来标记块的大小,而实体的最后一块会使用0(CR+LF)
来标记。
对于非持久连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界;而对于持久连接,这种方法显然不奏效,尽管已经发送完所有数据,但浏览器并不知道这一点,它无法得知这个打开的连接上是否还会有新数据进来,只能傻傻地等
要解决上面这个问题,最容易想到的办法就是计算实体长度,并通过头部告诉对方。这就要用到Content-Length
了
由于Content-Length
字段必须真实反映实体长度,但实际应用中,有些时候实体长度并没那么好获得,例如实体来自于网络文件,或者由动态语言生成。这时候要想准确获取长度,只能开一个足够大的 buffer,等内容全部生成好再计算。但这样做一方面需要更大的内存开销,另一方面也会让客户端等更久。
Transfer-Encoding
正是用来解决上面这个问题的。历史上Transfer-Encoding
可以有多种取值,为此还引入了一个名为 TE 的头部用来协商采用何种传输编码。但是最新的 HTTP 规范里,只定义了一种传输编码:分块编码(chunked)。
分块编码相当简单,在头部加入Transfer-Encoding: chunked
之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的CRLF(\r\n)
,也不包括分块数据结尾的CRLF
。最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束 [2]
例子:
HTTP/1.1 200 OK
...
Content-Encoding:gzip
Transfer-Econding:chunked
...
cf0 <!--转为10进制为:3312-->
... <!--3312字节的内容-->
392 <!--转为10进制为:914-->
... <!--914字节的内容-->
0 <!--分块结束-->
4. Trailer
<!--在报文主体之后还有Date头信息-->
Trailer:Date
该指令指示在报文主体之后还有哪些头信息,不可以包含以下头信息 [3]:
- 用于信息分帧的首部 (例如
Transfer-Encoding
和Content-Length
) - 用于路由用途的首部 (例如
Host
) - 请求修饰首部 (例如控制类和条件类的,如
Cache-Control
,Max-Forwards
,或者TE
) - 身份验证首部 (例如
Authorization
或者Set-Cookie
) Content-Encoding
,Content-Type
,Content-Range
,以及Trailer
自身
可应用于分块传输编码,如:
HTTP/1.1 200 OK
...
Content-Encoding:gzip
Transfer-Econding:chunked
Trailer:Date
...
cf0 <!--转为10进制为:3312-->
... <!--3312字节的内容-->
392 <!--转为10进制为:914-->
... <!--914字节的内容-->
0 <!--分块结束-->
Date:Sun Oct 17 15:08:00 2021
为什么还需要这个字段?直接把头信息放到前面不就好了吗?
这时因为有些信息只有处理完实体内容后才知道。比如一个字节流的大小、消息的完整性验证,消息经过处理后的最终状态等。这时,就需要是使用`Trailer`将信息加到实体的后面
5.Upgrade
询问下一个直连服务器,是否可以使用其他的协议进行通信
<!--询问对方是否可以使用 TLS/1.0或者webSocket协议进行通信-->
Upgrade:TLS/1.0,webSocket
为什么使用`Upgrade`的时候,要配合`Connection:Upgrade`一起使用?
再回到HTTP 1.1的Connection头部,这儿有一个兼容性问题:我们以Upgrade头部为例,某个proxy实现了HTTP 1.0协议,将Upgrade原样转发给后端,后端和proxy升级协议,但是这个情况下,proxy不认识升级后的协议啊 [4]。
如果服务器决定升级这个连接,会返回 101 Switching Protocols
状态码,和要切换的协议,如:
客户端发起请求
GET / HTTP/1.1
...
Connection:Upgrade
Upgrade:TLS/1.0,webSocket <!--询问本次通讯是否可以使用`TLS 1.0`或者`webSocket`协议-->
...
服务器给与回应
HTTP/1.1 101 Switching Protocols
...
Upgrade:TLS/1.0 <!--本次通讯可以使用`TLS 1.0`协议-->
...
如果不能使用其他协议,会返回常规的响应,例如:200 OK
注意: 由HTTP/1.1请求建立的连接可以升级为HTTP/2协议的连接,但是反过来不可以。事实上HTTP/2已经不再支持101状态码了,也不再支持任何连接升级机制。[5]
6.Via
<!-- 经过的1个代理地址为:p1.example.com,使用的Http协议版本是1.0 经过的2个代理地址为:p1.example.com,使用的Http协议版本是1.1 -->
Via: 1.0 p1.example.com, 1.1 p2.example.net
这个首部由代理服务器添加,每经过一个代理服务器,代理服务器会在Via
后面添加一条信息。可以用来追踪消息转发情况
7. Warning
HTTP/1.1
的Warning
首部是从HTTP/1.0
的响应首部Retry-After
演变过来的。该首部通常会告知用户一些与缓存相关的问题的警告。
Warning
的格式如下:
Warning: <警告码> <警告的主机:端口号> "<警告内容>" [<警告时间>]
警告码[6]
1XX
:警告码描述了关于当前响应的新鲜度或者验证状态的警告信息,并且将会在验证之后被缓存服务器删除。2XX
:警告码描述了验证之后不会被修复的某些展现内容方面的警告信息,并且在验证之后不会被缓存服务器删除。
7种警告码
警告码 | 文字描述 | 详细说明 |
---|---|---|
110 | Response is stale (响应已过期) | 代理返回的资源已过期 |
111 | Revalidate failed (再验证失败) | 代理再验证资源有效性时失败 |
112 | Disconnected Operation(断开链接操作) | 代理无法连接互联网 |
113 | Heuristic Expiration(试探性过期) | 响应的使用期超过24小时 (有效缓存的设定时间为24小时的情况下) |
199 | Miscellaneous Warning (杂项警告) | 任意的警告内容 |
214 | Transformation Applied(使用了转换) | 代理返回的展现内容进行了某些处理,比如改变了内容编码、媒体类型等。 |
299 | Miscellaneous Warning | 与199类似,只不过指代的是持久化警告。 |
下篇文章:Http头信息(二)——请求头信息(一)
关注我,获取最新的更新
Reference
[1]. Transfer-Encoding
[2]. HTTP 协议中的 Transfer-Encoding
[3]. Trailer
[4]. 为什么HTTP Upgrade的时候,需要Connection: upgrade
[5]. 协议升级机制
[6]. Warning
文章评论