HTTP报文

HTTP简介

超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。现在主要使用的是HTTP1.1 协议。

HTTP是无状态协议,不会保存多次请求之间的关系,可以使用cookie和session搭配做状态管理。

HTTP报文

用于HTTP协议交互的信息叫做HTTP报文,报文由报文首部和报文主体来组成,其中需要用空行分割报文首部和报文主体。报文首部包含报文行和报文头。

  • 报文首部:服务端或者客户端需要处理的请求或者响应的内容及其属性
  • 报文主体:服务端或者客户端需要发送的数据

HTTP报文分为请求报文和响应报文,请求报文和响应报文的报文结构不一样,其中最大的区别就是在报文首部中,各有各的特定的头部字段。

js 复制代码
报文行
报文头

报文体

HTTP报文头是在HTTP响应中发送的元数据信息,用于描述响应的特性、内容和行为。它们以键值对的形式出现,每个键值对由一个标头字段和一个相应的值组成。如下所示:

js 复制代码
Access-Control-Allow-Origin:*
Cache-Control:public, max-age=0, must-revalidate
Content-Type:text/html; charset=utf-8
Server:nginx
Date:Mon, 08 Jan 2024 18:32:47 GMT

请求报文

请求报文是由客户端发送的报文。

  • 请求行:包含用于请求的方法,请求地址和HTTP协议版本
  • 请求首部字段:请求报文里特有的请求头的标头字段
  • 通用首部字段:请求头和响应头都会用到的标头字段
  • 实体首部字段:针对请求报文的实体部分使用的标头字段
  • 其他:可能包含HTTP的RFC里未定义的标头字段(如Cookie、Authorization等)

响应报文

响应报文是由服务端发送的报文。

  • 状态行:包含响应结果的状态码,原因短语和HTTP版本
  • 响应首部字段:响应报文里特有的响应头的标头字段
  • 通用首部字段:请求头和响应头都会用到的标头字段
  • 实体首部字段:针对响应报文的实体部分使用的标头字段
  • 其他:可能包含HTTP的RFC里未定义的标头字段(如Set-Cookie等)

HTTP报文首部

HTTP1.1 规定了47种报文头的标头字段。

通用标头字段

标头字段 解释
1.Cache-Control 控制缓存的行为
2.Connection 决定当前的事务完成后,是否会关闭网络连接
3.Date 创建报文的日期和时间
4.Pragma 报文指令
5.Trailer 报文末端的首部一览
6.Transfer-Encoding 指定报文主体的传输编码方式
7.Upgrade 升级为其他协议
8.Via 代理服务器的相关信息
9.Warning 错误通知

Cache-Control

Cache-Control 通过设置不同的指令可以控制缓存的行为,指令格式为:

js 复制代码
// 控制可缓存性
Cache-Control: no-cache 
Cache-Control: no-store
// 控制到期时间
Cache-Control: max-age=<seconds> 

指令参数可以分为三类:

  • 控制可缓存性
  • 控制到期时间
  • 控制重新验证&重新加载

控制缓存

  1. no-cache:会强制验证数据的有效期,以防止获取到过期资源
  2. no-store:会禁止缓存服务器缓存数据,一般意味着数据中含有机密信息
  3. only-if-cached:仅从缓存服务器获取数据,保证请求不会达到源服务器,如果缓存服务器没有该资源,则返回状态码504(GateWay Timeout)
  4. public:表明响应可以被任何对象缓存,包括发送请求的客户端、代理服务器等
  5. private:表明响应只能被单个用户缓存,不能作为共享缓存,即代理服务器不能缓存

控制到期时间

  1. max-age:设置缓存存储的最大周期,超过这个时间缓存被认为过期 (单位秒),客户端只接收缓存时间为max-age=<seconds>的数据
  2. s-maxage:覆盖 max-ageExpires 字段,但它只适用于共享缓存例如代理服务器,私有服务器会忽略这个字段
  3. max-stale:表示客户端愿意接收一个过期的资源,只要资源的过期时间max-stale的值。
  4. min-fresh:表示客户端想要的资源至少在指定的秒数内仍然是新鲜的

HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略

控制重新验证和重新加载

  1. proxy-revalidate:要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性,与 must-revalidate 的功能相同。
  2. no-transform:禁止对资源进行转换,Content-EncodingContent-RangeContent-Type 标头不得被代理修改。例如,一个不透明的代理可能会在图像格式之间进行转换,以节省缓存空间或减少慢速链接上的流量,而这个行为会被 no-transform 禁止。

示例

js 复制代码
// 1.禁止缓存:
Cache-Control: no-store
//2.缓存静态资源并设置缓存时间,例如图像,CSS 文件和 JavaScript 文件
Cache-Control:public, max-age=31536000 
//3.需要重新验证
Cache-Control: no-cache 0
Cache-Control: max-age=0, must-revalidate 

指定 no-cachemax-age=0, must-revalidate 都表示客户端可以缓存资源,每次使用缓存资源前都必须重新验证其有效性。这意味着每次都会发起 HTTP 请求,但当缓存内容仍有效时可以跳过 HTTP 响应体的下载。

Connection

Connection决定当前的事务完成后,是否会关闭网络连接。如果该值是keep-alive,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。

从 HTTP/1.1 版本开始,所有连接默认为持久连接。

Date

表明 HTTP 报文的创建日期和时间。日期时间格式有好几种,一种常见格式为:Mon, 06 Feb 2023 01:19:14 GMT

Pragma

Pragma 是一个在 HTTP/1.0 中规定的通用标头字段,在HTTP/1.1 协议被 Cache-Control 代替。现在它用来向后兼容只支持 HTTP/1.0 协议的缓存服务器。

Trailer

Trailer在分块传输编码时会被用到,它用来在消息块后面添加额外的元信息(报文主体内容传输完成之后补充报文头的信息)。

示例:下面的响应报文中 Trailer 指定了 Expires 字段,在响应体后面出现了 Expires 字段。

js 复制代码
HTTP/1.1 200 OK
Date: Tue, 03 Jul 2012 04:40:56 GMT 
Content-Type: text/html
...
Transfer-Encoding: chunked 
Trailer: Expires
...(报文主体)...

Expires: Tue, 28 Sep 2004 23:59:59 GMT

Transfer-Encoding

规定传输报文时采用的编码方式,可选的编码方式如下。

Transfer-Encoding 是一个逐跳传输消息的报文首部的标头字段,即仅应用于两个节点之间的消息传递。如果想要将压缩后的数据应用于整个连接,那么应该使用端到端传输消息的报文首部标头字段 Content-Encoding 。

逐跳意思就是计算机A发送的报文是一跳一跳的来到计算机B的,网络1==》路由器1==》网络2==》路由器2==》网络3==》计算机B

chunked

js 复制代码
HTTP/1.1 200 OK
Date: Tue, 03 Jul 2012 04:40:56 GMT 
Cache-Control: public, max-age=604800 
Content-Type: text/javascript; charset=utf-8 
Expires: Tue, 10 Jul 2012 04:40:56 GMT 
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block 
Content-Encoding: gzip
Transfer-Encoding: chunked
Connection: keep-alive

cf0\r\n                                 ←长度16进制(10进制长度为33123312字节数据) 
123456789012345678901234567\r\n         ←33123312字节具体的数据内容
392\r\n                                 ←长度(10进制长度为914字节) 
123456789\r\n
0\r\n
\r\n

分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。数据分解成一系列数据块,并以一个或多个块发送,这样可以发送数据而不需要预先知道发送内容的总大小。

在头部加入 Transfer-Encoding: chunked 之后,就代表这个报文采用了分块编码。这时,报文中的实体需要改为用一系列分块来传输。

每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的CRLF(\r\n)。

最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。

compress

采用 Lempel-Ziv-Welch (LZW) 压缩算法,这种内容编码方式已经被大部分浏览器弃用。

deflate

采用 zlib 结构,和 deflate 压缩算法。

gzip

表示采用 Lempel-Ziv coding (LZ77) 压缩算法,以及 32 位 CRC 校验的编码方式。这个编码方式最初由 UNIX 平台上的 gzip 程序采用。出于兼容性的考虑,HTTP/1.1 标准提议支持这种编码方式的服务端应该识别作为别名的 x-gzip 指令。

identity

用于表明自身未经过压缩和修改。

Upgrade

用于允许将一个已建立的连接升级成新的、不相容的协议。

HTTP/2 明确禁止使用此机制,这个机制只属于 HTTP/1.1

如果使用了 Upgrade 字段,Connection 字段的值会被指定为 Upgrade,比如:

js 复制代码
GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: TLS/1.0

如果服务端决定升级这次连接,就会返回一个 101 Switching Protocols 响应状态码和原因短语,以及一个要切换到的协议的标头字段 Upgrade。如果服务端没有或者不能升级这次连接,它会忽略客户端发送的 Upgrade 标头字段,返回一个常规的响应:例200 OK

在服务端发送 101 状态码之后,服务端可以使用新协议,并根据需要然后执行任何额外的特定于协议的握手。实际上,一旦这次升级完成了,连接就变成了双向管道。并且可以通过新协议完成启动升级的请求。

最经常会需要升级一个 HTTP 连接的场合就是使用 WebSocket,它总是通过升级 HTTP 或 HTTPS 连接来实现。当使用 WebSocket API 以及其他实现 WebSocket 的库去建立新的连接时,基本上都不用操心升级的过程,因为这些 API 已经实现了这一步。

js 复制代码
const webSocket = new WebSocket("ws://destination.server.ext", "optionalProtocol");

可以用 wss://URL 方式来打开安全的 WebSocket 连接

WebSocket() 构造函数已经自动完成了发送初始 HTTP/1.1 连接的所有工作,然后为客户端处理握手及升级过程。

如果想要自己重头实现 WebSocket 连接,就必须要处理握手和升级过程。在创建初始 HTTP/1.1 会话之后,客户端需要发送另一个 HTTP 标准请求来请求升级,但在请求头中要带上 Upgrade和 Connection,也就是:

js 复制代码
Connection: Upgrade
Upgrade: websocket

Via

用于跟踪请求和响应经过的代理服务器信息。它允许客户端和服务端了解请求和响应的路径,以及它们是否经过了代理服务器。Via标头字段在HTTP请求和响应的报文头部中使用,并由代理服务器自动添加和更新。

js 复制代码
Via: [ <protocol-name> "/" ] <protocol-version> <host> [ ":" <port> ]
Via: [ <protocol-name> "/" ] <protocol-version> <pseudonym>
// 多个代理部分之间由逗号分隔
Via: 1.1 proxy.example.com:8080, 1.1 forward-proxy.example.net

Via标头字段由多个部分组成,每个部分表示一个经过的代理服务器。每个部分由以下内容组成:

  • <protocol-name>协议版本:代理服务器使用的HTTP协议版本,例如HTTP/1.1
  • <protocol-version>代理服务器地址:代理服务器的域名或IP地址
  • <host> <port>代理服务器端口:代理服务器监听的端口号
  • <pseudonym>注释:可选项,用于提供额外信息,例如内部代理服务器的软件和版本

作用:

  • 路径跟踪:通过Via标头字段,客户端和服务端可以了解请求和响应的传输路径,包括经过的代理服务器和它们的顺序
  • 反向代理检测:服务端可以通过Via标头字段判断请求是否经过了反向代理服务器,以便做出不同的处理
  • 防止循环:Via标头字段可以用于检测请求或响应在代理服务器之间发生循环转发的情况,防止请求和响应在代理服务器之间无限循环

Warning

警告报文出现了问题,格式:Warning: <warn-code> <warn-agent> <warn-text> [<warn-date>]

请求标头字段

标头字段 解释
1.Accrpt 用户代理可处理的媒体类型
2.Accrpt-Charset 优先的字符集
3.Accept-Encoding 优先的内容编码
4.Accept-Language 优先的语言(自然语言)
5.Authorization web认证信息
6.Expect 期待服务器的特定行为
7.From 用户的电子邮箱地址
8.Host 请求资源所在服务器
9.If-Match 比较实体标记(ETag)
10.If-Modified-Since 比较资源的更新时间
11.If-None-Match 比较实体标记(与If-Match相反)
12.If-Range 资源未更新时发送实体Byte的范围请求
13.If-Unmodified-Since 比较资源的更新时间(与If-Modified-Since相反)
14.Max-Forwards 最大传输逐跳数
15.Proxy-Authorization 代理服务器要求客户端的认证信息
16.Range 实体的字节范围要求
17.Referer 对请求中URI的原始获取方
18.TE 传输编码的优先级
19.User-Agent HTTP客户端程序的信息

Accept

用来告知服务器可以处理的内容类型,例如:

js 复制代码
// 格式
Accept: <MIME_type>/<MIME_subtype>
Accept: <MIME_type>/*
Accept: */*
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
  • <MIME_type>/<MIME_subtype>,比如 text/html
  • * 代表任意类型,比如 image/* 可以用来指代 image/pngimage/svgimage/gif 以及任何其他的图片类型
  • q 代表权重

Accept-Charset

用于声明客户端可以处理的字符集类型

js 复制代码
Accept-Charset: <charset>
Accept-Charset: utf-8, iso-8859-1;q=0.5, *;q=0.1

Accept-Encoding

用于声明客户端能够处理的编码方式

js 复制代码
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5

Accept-Language

用于声明客户端可以理解的语言

js 复制代码
Accept-Language: <language>
Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5

Authorization

用于提供给服务器验证身份的凭据,允许其访问受保护的资源

js 复制代码
Authorization: <auth-scheme> <authorization-parameters>
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l

Basic身份验证(基础认证):首先将用户名和密码使用一个冒号拼接(username:password),然后将生成的字符串进行 base64 编码。除了 Basic 编码方式,还有 Digest、Negotiate 等方式。

五种主要认证机制:

  • 基础认证:尽管实现简单,但需要结合 HTTPS 使用以确保其安全性,因为其编码方式易于解码。
  • 摘要认证:通过使用比如 MD5 的散列函数来传输密码,其安全性高于基础认证,但在现代应用中相对较少使用。
  • 令牌认证(例如 Bearer 令牌):作为一种更安全的认证方式,特别适用于 RESTful API,并广泛用于现代网络应用中。
  • OAuth:作为授权的开放标准,允许第三方应用安全地访问用户在另一服务提供商上的数据,无需用户直接向第三方提供凭证。
  • API 密钥:虽易于使用,但因安全性相对较低,常结合其他安全措施一起使用,适用于安全要求不极高的场景。

Expect

客户端发送带有 Expect 请求头的请求,等服务器回复后再发送请求体

js 复制代码
Expect: 100-continue

服务端检查请求头,可能会返回一个状态码为 100 (Continue) 的回复来告知客户端继续发送请求体,也可能会返回一个状态码为 417 (Expectation Failed) 的回复来告知客户端要求不能得到满足。

From

附带一个电子邮箱地址

js 复制代码
From: webmaster@example.org

Host

指明本次请求的目标服务器主机名和端口号

如果没有包含端口号,会自动使用被请求服务的默认端口。所有 HTTP/1.1 请求报文中必须包含一个 Host 请求头字段。对于缺少 Host 头或者含有多个 Host 头的 HTTP/1.1 请求,可能会收到 400(Bad Request)状态码。

If-Match

形如 If-xxx 这种样式的请求头字段,都可称为条件请求。服务端接收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。

js 复制代码
If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"
If-Match: *

服务端会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。还可以使用 * 号指定If-Match的字段值,如果这样的话,那么服务器将会忽略ETag的值,只要资源存在就处理请求。

If-Modified-Since

用于确认客户端拥有的本地资源的有效性

js 复制代码
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

服务端在收到带有 If-Modified-Since 字段的请求后,会将该字段值和资源更新时间做比较,若资源没有更新,则返回 304 状态码(Not Modified)。

If-None-Match

与 If-Match 的作用相反,只有在If-None-Match的字段值与ETag值不一致时,服务端才会处理该请求

If-Range

告知服务器若指定的If-Range字段值(ETag值或者时间)和请求资源的ETag值或时间一致时,则服务端作为范围请求处理,否则服务端需要返回全体资源

js 复制代码
If-Range: Wed, 21 Oct 2015 07:28:00 GMT 

字段值中既可以用 Last-Modified 时间值用作验证,也可以用 ETag 标记作为验证,但不能将两者同时使用

If-Unmodified-Since

与 If-Modified-Since 作用相反,指定的请求资源只有在字段值内指定的日期时间之后未发生更新,才会执行这个请求,否则,返回412 Precondition Failed状态响应

Max-Forwards

用于限制 TRACE 方法可经过的服务器数目(通常指代理服务器)。发送请求头包含Max- Forwards字段的请求时,该字段以十进制整数形式指定可经过的服务器最大数目。每经过一个服务器,Max-Forwards 的值减 1。当服务器接收到 Max-Forwards 值为 0 的请求时,则不再进行转发,而是直接返回响应。

有可能这个请求经过了多台服务器代理转发,如果突然间请求出现了什么问题导致转发失败,而客户端不知道,此时就可以用此属性来定位问题,这个时候我们就可以掌握一个出问题的转发路径,从而方便进一步的排查问题

Proxy-Authorization

用于客户端和代理服务器之间的认证

js 复制代码
Proxy-Authorization: Basic dGlwOjkpNLAGfFY5

Range

Range 字段用于分批请求资源,适用于只需要获取部分资源的范围请求,下面的示例表示请求获取从第 5001 字节至第 10000 字节的资源。

js 复制代码
Range: bytes=5001-10000

服务端接收到请求头附带 Range字段时,会在处理请求之后返回状态码为 206 Partial Content 的响应。无法处理该范围请求时,则会返回状态码 200 OK 的响应及全部资源。

Referer

Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。

Referer 请求头可能暴露用户的浏览历史,涉及到用户的隐私问题,所以一般用于 HTTPS 协议。

TE

表明客户端能够处理的传输编码方式及相对优先级

js 复制代码
TE: gzip, deflate;q=0.5

User-Agent

User-Agent字段包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。比如 Google 的 UA 字符串:

js 复制代码
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36

响应标头字段

响应头字段名 解释
1.Accept-Ranges 是否接受字节范围请求
2.Age 推算资源创建经过时间
3.ETag 资源的匹配信息
4.Location 令客户端重定向至指定URI
5.Proxy-Authenticate 代理服务器对客户端的认证信息
6.Retry-After 对再次发起请求的时机要求
7.Server HTTP服务器的安装信息
8.Vary 代理服务器缓存的管理信息
9.WWW-Authenticate 服务器对客户端的认证信息

Accept-Ranges

表明服务端是否支持范围请求,可以处理范围请求时指定字段值为 bytes,反之则为 none,指令格式:

js 复制代码
// 可以处理范围请求
Accept-Ranges: bytes
// 不可以处理范围请求
Accept-Ranges: none

Age

可以告知客户端,源服务器多久之前创建了资源,单位是秒。若创建该响应的是缓存服务器,则Age值是指资源在代理服务器缓存了多久。代理创建响应时必须加上首部字段Age。

js 复制代码
Age: 24

ETag

ETag 是资源以字符串形式的唯一标识符,使用 ETag 能快速确定资源是否发生过变化。服务器会为每份资源分配对应的ETag值,资源被更新时,ETag值也会被更新,并没有统一的算法规则,而是由服务器来分配

ETag 有强弱之分:

  • ETag:无论资源发生多么细微的变化都会改变其值
  • ETag:只用于提示资源是否相同,只有资源发生了根本的改变才会改变ETag值,这时会在字段值最开始加W/
js 复制代码
ETag: W/"0815"
ETag:W/"XXX"

Location

使用该响应字段可以将响应接收方引导至某个与请求的URL位置不同的资源,一般与3XX Redirection的响应状态码配合使用,将页面重定向至新的地址

js 复制代码
Location: <url>

Proxy-Authenticate

用于把代理服务器所要求的认证信息发送给客户端

js 复制代码
Proxy-Authenticate: Basic realm="Access to the internal site"

Retry-After

用于告知客户端应该在多久之后再次发送请求。主要配合状态码 503 Service Unavailable,或 3xx Redirect 响应一起使用

js 复制代码
Retry-After: 120(以秒为单位)

Server

表明服务器的软件和版本信息

js 复制代码
Server: Apache/2.2.6 (Unix) PHP/5.2.5

Vary

对缓存进行控制,源服务器会向代理服务器传达关于本地缓存使用方法的命令。

js 复制代码
Vary: *
Vary: <header-name>, <header-name>, ...
  • * :表示不使用缓存,决定缓存能否使用,建议用Cache-Control: no-store而非Vary: *
  • header-name :表示 HTTP 头,可以有多个

示例

示例1:

相同页面在 HTTP 传输过程中使用了不同压缩算法,如果不能正确区分,会造成页面打开错误。服务端响应头返回Vary:Content-Encoding来建立跟压缩算法相关的缓存,客户端通过请求头发送Accept-Encoding:编码格式 明确需要的算法类型,从而获得正确的缓存资源

  • Client1 向代理服务器请求 /doc 页面,共享缓存Cache为空,向源服务器发请求,代理服务器收到页面数据并发送给Client1,同时缓存此次页面

  • Client2 向代理服务器请求 /doc 页面,代理服务器查找无对应缓存,向源服务器发请求来响应Client2,代理服务器收到页面数据并发送给Client2,同时缓存此次页面;

  • Client3 向代理服务器请求 /doc 页面,代理服务器查找到缓存,直接把缓存发送给Client3

示例2:

  • 当代理服务器接收到服务端返回包含Vary指定项的响应后,仅对请求中含有相同Vary的 HTTP 头的请求返回缓存
  • 即使对相同资源发起请求,但是由于Vary指定的 HTTP 头不相同,因此必须从源服务器重新获取资源

以下使用的Accept-Language:en-us字段的值相同,那么直接从缓存返回响应,否则从源服务器请求资源后再返回响应

示例3: 网站为了让 电脑 和 手机 都能访问,通常会有两个版本。手机先访问网站,产生了手机版缓存,之后电脑也访问了,获得了手机版缓存,这样显示页面必然会产生错误。服务端返回Vary: User-Agent针对不同设备生成不同缓存。客户端请求时带上 User-Agent 字段的响应头,明确设备类型。过程跟上图类似,只是创建和寻找缓存的依据,换成了 User-Agent。

WWW-Authenticate

定义了应该使用何种验证方式去获取对资源的连接,例如服务端利用该字段规定了 Basic 认证

js 复制代码
WWW-Authenticate: Basic realm="Access to the staging site"

报文实体字段

字段名 解释
1.Allow 资源可支持的HTTP方法
2.Content-Encoding 实体主体适用的编码方式
3.Content-Language 实体主体的自然语言
4.Content-Length 实体主体的大小(单位:字节)
5.Content-Location 代替对应资源的URI
6. Content-MD5 实体主体的报文摘要
7. Content-Range 实体主体的位置范围
8. Content-Type 实体主体的媒体类型
9.Expires 实体主体过期的日期时间
10.Last-Modified 资源的最后修改日期时间

Allow

用于枚举资源所支持的 HTTP 方法的集合

js 复制代码
Allow: GET, HEAD

如果 Allow 字段的值为空,说明资源不接受使用任何 HTTP 方法的请求,这可能是因为服务端需要临时禁止对资源的任何访问。

Cotent-Encoding

消息文本的编码类型

js 复制代码
Content-Encoding: deflate, gzip

指令参数:

  • gzip 表示采用 Lempel-Ziv coding (LZ77) 压缩算法,以及 32 位 CRC 校验的编码方式。
  • compress 表示采用 Lempel-Ziv-Welch (LZW) 压缩算法。
  • deflate 表示采用 zlib 结构和 deflate 压缩算法。
  • br 表示采用 Brotli 算法的编码方式。

Cotent-Language

Content-Language 用来说明服务端希望客户端采用的语言或语言组合,例如报文的Content-Language字段值为de,那么说明这份文件是为说德语的人提供的,但是这并不意味着文本是德文,它也可能是英文等其他语言:

js 复制代码
Content-Language: de

Content-Length

用于指明发送给客户端的消息主体的大小,用十进制数字表示

js 复制代码
Content-Length: 15900

Content-Location

对应资源的URL。

Content-Range

用来表示一个数据片段在整个文件中的位置

js 复制代码
Content-Range: bytes 200-1000/67589

Content-Type

用于告知客户端响应报文内容的内容类型

js 复制代码
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
  • media-type资源的MIME类型,比如 text/html、multipart/form-data。
  • charset字符编码标准。

Expires

用于告知客户端缓存的失效日期

js 复制代码
Expires: Wed, 21 Oct 2015 07:28:00 GMT

如果在Cache-Control响应头设置了 max-age 或者 s-max-age 指令,那么 Expires 头会被忽略

Last-Modified

资源最后一次修改的时间

js 复制代码
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

其他字段(cookie)

服务端利用 Set-Cookie 字段来告知客户端 cookie,例如设置一个永久 cookie:

js 复制代码
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
属性 解释
NAME=VALUE 赋予Cookie的名称和其值(必需项)
expires = DATE Cookie的有效期(若不指定则默认为浏览器关闭为止)
path=PATH 将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的文件目录)
domin=域名 作为Cookie适用对象的域名(若不指定则默认为创建Cookie的服务器域名)
Secure 仅在HTTPS安全通信时才会发送Cookie
HttpOnly 加以限制,使Cookie不能被JS脚本访问,主要目的是为了防止跨站脚本攻击(Cross Site Scripting,XSS)对cookie的窃取

会话期 cookie:

js 复制代码
Set-Cookie: sessionId=38afes7a8 

会话期 cookie 将会在客户端关闭时被移除。会话期 cookie 不设置 Expires 或 Max-Age 属性。

持久化 cookie:

js 复制代码
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT 
Set-Cookie: id=a3fWa; Max-Age=2592000

持久化 cookie 不会在客户端关闭时失效,而是在特定的日期(Expires)或者经过一段特定的时间之后(Max-Age)才会失效。

客户端在向服务器发 HTTP 请求时附带 Cookie 以获得服务器的认证。(Cookie 值来源于上文的 Set-Cookie 字段值)

报文头部字段的转发策略

一个 HTTP 请求要跨过多个代理服务器,经过多次代理服务器的转发才能到达目标服务器。

代理服务器做转发时,对原HTTP报文头部字段有两种处理方式:

  1. 逐跳策略:单次转发有效。
  2. 端到端策略:一直有效,确保字段被发送到目标服务器。

除了下面这些字段为逐跳策略外,其他字段都属于端到端策略:

  • Connection
  • Keep-Alive
  • Proxy-Authenticate
  • Proxy-Authorization
  • Trailer
  • TE
  • Transfer-Encoding
  • Upgrade

容易混淆的字段

TE、Accept-Encoding、Transfer-Encoding、Content-Encoding

  1. Transfer-Encoding:用于指定传输报文主体时使用的编码方式,属于逐跳首部,即只在两个节点间有效。
  2. TE:用于告知服务端,客户端能够处理的编码方式和相对优先级,属于逐跳首部,即只在两个节点间有效。
  3. Content-Encoding:用于指定报文主体已经采用的编码方式,属于端到端首部,即在整个传输过程中有效。
  4. Accept-Encoding:用于告知服务端,客户端能够处理的编码方式和相对优先级,属于端到端首部,即在整个传输过程中有效。

Loaction 与 Content-Location

Location 指定的是一个重定向请求的目的地址(或者新创建的文件的 URL)。Content-Location 指向的是可供访问的资源的直接地址。

Proxy-Authenticate、WWW-Authenticate

Proxy-Authenticate 规定了客户端与代理服务器的认证方式,而 WWW-Authenticate 规定了客户端与服务端的认证方式。

有关联的字段

ETag、If-Match、If-None-Match

Etag由服务端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match,比如请求一个文件的流程可能如下:

第一次请求:

  1. 客户端发起 HTTP GET 请求一个文件;
  2. 服务端处理请求,返回文件内容和一堆Header,当然包括Etag(例如"2e681a-6-5d044840")。

第二次请求:

  1. 客户端发起 HTTP GET 请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头的内容就是第一次请求时服务器返回的Etag:2e681a-6-5d044840。
  2. 服务器判断发送过来的Etag和计算出来的Etag匹配,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;

Cache-Control、max-age、Expires

当首部字段 Cache-Control 有指定 max-age 指令时,会优先处理 max-age 指令,而忽略 Expires 字段。

相关推荐
摸鱼的春哥4 分钟前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响7 分钟前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
C澒13 分钟前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅14 分钟前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘16 分钟前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
恋猫de小郭1 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端