「HTTP」HTTP 首部

292 阅读22分钟

1 HTTP 报文首部

在请求中,HTTP 报文由方法、URI、HTTP 版本、HTTP 首部字段等部分构成。

在响应中,HTTP 报文由 HTTP 版本、状态码、HTTP 首部字段 3 部分构成。

首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。

2 HTTP 首部字段

2.1 HTTP 首部字段传递重要信息

使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的 语言、认证信息等内容。

2.2 HTTP 首部字段结构

HTTP 首部字段是由首部字段名和字段值构成的,中间用冒号“:” 分隔。字段值对应单个 HTTP 首部字段可以有多个值。

Keep-Alive: timeout=15, max=100

2.3 4 种 HTTP 首部字段类型

  1. 通用首部字段:请求报文和响应报文两方都会使用的首部。
  2. 请求首部字段:从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
  3. 响应首部字段:从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。
  4. 实体首部字段:针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。

2.4 HTTP/1.1 首部字段一览

HTTP/1.1 规范定义了 47 种首部字段。在下几节详细说明。

2.5 非 HTTP/1.1 首部字段

不限于 RFC2616 中定义的 47 种首部字段,还有 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定义的首部字段,

2.6 End-to-end 首部和 Hop-by-hop 首部

HTTP 首部字段将定义成缓存代理和非缓存代理的行为,分成 2 种类 型。

  1. 端到端首部:分在此类别中的首部会转发给请求 / 响应对应的最终接收目标,且必须保存在由缓存生成的响应中,另外规定它必须被转发。
  2. 逐跳首部:分在此类别中的首部只对单次转发有效,会因通过缓存或代理而不再转发。HTTP/1.1 和之后版本中,如果要使用 hop-by-hop 首部,需提供 Connection 首部字段。

3 HTTP/1.1 通用首部字段

3.1 Cache-Control

Cache-Control 能够控制缓存的行为。

Cache-Control: private, max-age=0, no-cache
指令说明
表示是否能缓存的指令
public则明确表明其他用户也可利用缓存
private响应只以特定的用户作为对象
no-cache防止从缓存中返回过期的资源。客户端:不会接收缓存过的响应;服务器:缓存前必须先确认其有效性
控制可执行缓存的对象的指令
no-store暗示请求或响应中包含机密信息,缓存不能在本地存储请求或响应的任一部分
指定缓存期限和认证的指令
s-maxage只适用于供多位用户使用的公共缓存服务器,使用时忽略 Expires 和 max-age
max-age客户端:获取资源有效性的最长时间,服务器:资源保存为缓存的最长时间,使用时忽略 Expires(HTTP/1.1)
min-fresh要求缓存服务器返回至少还未过指定时间的缓存资源
max-stale可指示缓存资源,即使过期也照常接收
only-if-cached客户端仅在缓存服务器本地缓存目标资源的情况下才会要求其返回
must-revalidate代理会向源服务器再次验证即将返回的响应缓存目前是否仍然有效
proxy-revalidate所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性
no-transform无论是在请求还是响应中,缓存都不能改变实体主体的媒体类型,防止缓存或代理压缩图片等类似操作
Cache-Control 扩展
cache-extension token通过 cache-extension 标记(token),可以扩展 Cache-Control 首部字段内的指令。extension tokens 仅对能理解它的缓存服务器来说是有意义的。

3.2 Connection

Connection 首部字段具备如下两个作用:

  1. 控制不再转发给代理的首部字段

    在客户端发送请求和服务器返回响应内,使用 Connection 首部字 段,可控制不再转发给代理的首部字段(即 Hop-by-hop 首部)。

    GET / HTTP/1.1
    Upgrade: HTTP/1.1
    Connection: Upgrade
    
    GET / HTTP/1.1
    
  2. 管理持久连接

    HTTP/1.1 版本的默认连接都是持久连接。为此,客户端会在持久连接上连续发送请求。当服务器端想明确断开连接时,则指定 Connection 首部字段的值为 Close。

    Connection: close
    

    HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为 此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定 Connection 首部字段的值为 Keep-Alive。

    Connection: Keep-Alive
    

3.3 Date

首部字段 Date 表明创建 HTTP 报文的日期和时间。以 HTTP/1.1 版本的时间格式为例:

Date: Tue, 03 Jul 2012 04:40:59 GMT

3.4 Pragma

仅作为与 HTTP/1.0 的向后兼容而定义。为了兼容,一般同时使用以下两个首部字段:

Cache-Control: no-cache
Pragma: no-cache

3.5 Trailer

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

3.6 Transfer-Encoding

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

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
Trailer: Expires
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Content-Encoding: gzip
Transfer-Encoding: chunked
Connection: keep-alive

cf0 ←16进制(10进制为3312)

...3312字节分块数据...

392 ←16进制(10进制为914)

...914字节分块数据...

0
Expires: Tue, 10 Jul 2012 04:40:56 GMT

3.7 Upgrade

首部字段 Upgrade 用于检测 HTTP 协议及其他协议是否可使用更高的 版本进行通信,其参数值可以用来指定一个完全不同的通信协议。

对于附有首部字段 Upgrade 的请求,服务器可用 101 Switching Protocols 状态码作为响应返回。

3.8 Via

使用首部字段 Via 是为了追踪客户端与服务器之间的请求和响应报文的传输路径。

首部字段 Via 不仅用于追踪报文的转发,还可避免请求回环的发生。 所以必须在经过代理时附加该首部字段内容。Via 首部是为了追踪传输路径,所以经常会和 TRACE 方法一起使用。

3.9 Warning

该首部通常会告知用户一些与缓存相关的问题的警告。格式如下:

Warning: [警告码][警告的主机:端口号]“[警告内容]”([日期时间])

4 请求首部字段

4.1 Accept

Accept 首部字段可通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可使用 type/subtype 这种形式,一次指定多种媒体类型。

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0

q= 来格外表示权重值,用分号分隔,范围是 0~1,默认为 1。

4.2 Accept-Charset

Accept-Charset 首部字段可用来通知服务器用户代理支持的字符集及字符集的相对优先顺序。格式与 Accept 一致。

Accept-Charset: iso-8859-5, unicode-1-1;q=0.8

4.3 Accept-Encoding

Accept-Encoding 首部字段用来告知服务器用户代理支持的内容编码及内容编码的优先级顺序。格式与 Accept 一致。

Accept-Encoding: gzip, deflate

4.4 Accept-Language

首部字段 Accept-Language 用来告知服务器用户代理能够处理的自然语言集,以及自然语言集的相对优先级。格式与 Accept 一致。

Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3

4.5 Authorization

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

Authorization: Basic dWVub3NlbjpwYXNzd29yZA==

4.6 Expect

客户端使用首部字段 Expect 来告知服务器,期望出现的某种特定行为。因服务器无法理解客户端的期望作出回应而发生错误时,会返回状态码 417 Expectation Failed。

Expect: 100-continue

4.7 From

首部字段 From 用来告知服务器使用用户代理的用户的电子邮件地址。

通常,其使用目的就是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。使用代理时,应尽可能包含 From 首部字段。

From: info@hackr.jp

4.8 Host

首部字段 Host 会告知服务器,请求的资源所处的互联网主机名和端口号。Host 首部字段在 HTTP/1.1 规范内是唯一一个必须被包含在请求内的首部字段。

首部字段 Host 和以单台服务器分配多个域名的虚拟主机的工作机制有很密切的关联,这是首部字段 Host 必须存在的意义。

Host: www.hackr.jp

若服务器未设定主机名,那直接发送一个空值即可。

4.9 If-Match

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

首部字段 If-Match,属附带条件之一,它会告知服务器匹配资源所用的实体标记(ETag)值。这时的服务器无法使用弱 ETag 值。

服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。

还可以使用星号(*)指定 If-Match 的字段值。针对这种情况,服务器将会忽略 ETag 的值,只要资源存在就处理请求。

If-Match: "123456"

4.10 If-Modified-Since

首部字段 If-Modified-Since,属附带条件之一,它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源都没有过更新,则返回状态码 304 Not Modified 的响应。

If-Modified-Since 用于确认代理或客户端拥有的本地资源的有效性。 获取资源的更新日期时间,可通过确认首部字段 Last-Modified 来确定。

If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT

4.11 If-None-Match

首部字段 If-None-Match 属于附带条件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的实体标记(ETag)值与请求资源的 ETag 不一致时,它就告知服务器处理该请求。 在 GET 或 HEAD 方法中使用首部字段 If-None-Match 可获取最新的资 源。因此,这与使用首部字段 If-Modified-Since 时有些类似。

PUT /sample.html HTTP/1.1
If-None-Match: *

4.12 If-Range

首部字段 If-Range 属于附带条件之一。它告知服务器若指定的 If-Range 字段值(ETag 值或者时间)和请求资源的 ETag 值或时间相一致时,则作为范围请求处理。反之,则返回全体资源。

GET /index.html HTTP/1.1
If-Range: "123456"
Range: bytes=5001-10000

下面我们思考一下不使用首部字段 If-Range 发送请求的情况。服务器端的资源如果更新,那客户端持有资源中的一部分也会随之无效,当然,范围请求作为前提是无效的。这时,服务器会暂且以状态码 412 Precondition Failed 作为响应返回,其目的是催促客户端再次发送请求。这样一来,与使用首部字段 If-Range 比起来,就需要花费两倍的功夫。

4.13 If-Unmodified-Since

首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相反。它的作用的是告知服务器,指定的请求资源只有在字段值内指定的日期时间之后,未发生更新的情况下,才能处理请求。如果在指定日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应返回。

4.14 Max-Forwards

通过 TRACE 方法或 OPTIONS 方法,发送包含首部字段 Max-Forwards 的请求时,该字段以十进制整数形式指定可经过的服务器最大数目。服务器在往下一个服务器转发请求之前,Max-Forwards 的值减 1 后重新赋值。当服务器接收到 Max-Forwards 值为 0 的请求时,则不再进行转发,而是直接返回响应。

Max-Forwards: 10

可以使用这个字段对以产生问题的服务器为终点的传输路径的通信状况有所把握。

4.15 Proxy-Authorization

接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段 Proxy-Authorization 的请求,以告知服务器认证所需要的信息。与 Authorization 不同,认证行为发生在客户端与代理之间。

Proxy-Authorization: Basic dGlwOjkpNLAGfFY5

4.16 Range

对于只需获取部分资源的范围请求,包含首部字段 Range 即可告知服务器资源的指定范围。上面的示例表示请求获取从第 5001 字节至第 10000 字节的资源。

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

Range: bytes=5001-10000

4.17 Referer

首部字段 Referer 会告知服务器请求的原始资源的 URI,也就是该请求是从那个 Web 页面发起的。

客户端一般都会发送 Referer 首部字段给服务器。但当直接在浏览器的地址栏输入 URI,或出于安全性的考虑时,也可以不发送该首部字段。

Referer: http://www.hackr.jp/index.htm

4.18 TE

首部字段 TE 会告知服务器客户端能够处理响应的传输编码方式及相对优先级。它和首部字段 Accept-Encoding 的功能很相像,但是用于传输编码。

首部字段 TE 除指定传输编码之外,还可以指定伴随 trailer 字段的分块传输编码的方式。应用后者时,只需把 trailers 赋值给该字段值。

TE: gzip, deflate;q=0.5

4.19 User-Agent

首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传达给服务器。

由网络爬虫发起请求时,有可能会在字段内添加爬虫作者的电子邮件地址。此外,如果请求经过代理,那么中间也很可能被添加上代理服务器的名称。

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/201001

5 响应首部字段

5.1 Accept-Ranges

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

5.2 Age

首部字段 Age 能告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。

若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段 Age。

5.3 ETag

首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

另外,当资源更新时,ETag 值也需要更新。生成 ETag 值时,并没有统一的算法规则,而仅仅是由服务器来分配。

强 ETag 值和弱 Tag 值:

  • 强 ETag 值:不论实体发生多么细微的变化都会改变其值。

    ETag: "usagi-1234"
    
  • 弱 ETag 值:只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。

    ETag: W/"usagi-1234"
    

5.4 Location

使用首部字段 Location 可以将响应接收方引导至某个与请求 URI 位置不同的资源。

基本上,该字段会配合 3xx :Redirection 的响应,提供重定向的 URI。

5.5 Proxy-Authenticate

首部字段 Proxy-Authenticate 会把由代理服务器所要求的认证信息发送给客户端。

它与客户端和服务器之间的 HTTP 访问认证的行为相似,不同之处在于其认证行为是在客户端与代理之间进行的。而客户端与服务器之间进行认证时,首部字段 WWW-Authorization 有着相同的作用。

5.6 Retry-After

首部字段 Retry-After 告知客户端应该在多久之后再次发送请求。主要配合状态码 503 Service Unavailable 响应,或 3xx Redirect 响应一起使用。字段值可以指定为具体的日期时间,也可以是创建响应后的秒数。

5.7 Server

首部字段 Server 告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。不单单会标出服务器上的软件应用名称,还有可能包括版本号和安装时启用的可选项。

5.8 Vary

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

5.9 WWW-Authenticate

首部字段 WWW-Authenticate 用于 HTTP 访问认证。它会告知客户端适用于访问请求 URI 所指定资源的认证方案(Basic 或是 Digest)和带参数提示的质询(challenge)。状态码 401 Unauthorized 响应中, 肯定带有首部字段 WWW-Authenticate。realm 字段的字符串是为了辨别请求 URI 指定资源所受到的保护策略。

Proxy-Authenticate: Basic realm="Usagidesign Auth"

6 实体首部字段

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

6.1 Allow

首部字段 Allow 用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。

Allow: GET, HEAD

6.2 Content-Encoding

首部字段 Content-Encoding 会告知客户端服务器对实体的主体部分选用的内容编码方式。

6.3 Content-Language

首部字段 Content-Language 会告知客户端,实体主体使用的自然语言(指中文或英文等语言)。

6.4 Content-Length

首部字段 Content-Length 表明了实体主体部分的大小(单位是字节)。

6.5 Content-Location

首部字段 Content-Location 给出与报文主体部分相对应的 URI。和首部字段 Location 不同,Content-Location 表示的是报文主体返回资源对应的 URI。

6.6 Content-MD5

首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。

Content-MD5: OGFkZDUwNGVhNGY3N2MxMDIwZmQ4NTBmY2IyTY==

对报文主体执行 MD5 算法获得的 128 位二进制数,再通过 Base64 编码后将结果写入 Content-MD5 字段值。由于 HTTP 首部无法记录二进制值,所以要通过 Base64 编码处理。为确保报文的有效性,作为接收方的客户端会对报文主体再执行一次相同的 MD5 算法。计算出的值与字段值作比较后,即可判断出报文主体的准确性。

采用这种方法,对内容上的偶发性改变是无从查证的,也无法检测出恶意篡改。其中一个原因在于,内容如果能够被篡改,那么同时意味着 Content-MD5 也可重新计算然后被篡改。

6.7 Content-Range

针对范围请求,返回响应时使用的首部字段 Content-Range,能告知客户端作为响应返回的实体的哪个部分符合范围请求。字段值以字节为单位,表示当前发送部分及整个实体大小。

Content-Range: bytes 5001-10000/10000

6.8 Content-Type

首部字段 Content-Type 说明了实体主体内对象的媒体类型。和首部字段 Accept 一样,字段值用 type/subtype 形式赋值。

Content-Type: text/html; charset=UTF-8

6.9 Expires

首部字段 Expires 会将资源失效的日期告知客户端。缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求 资源。

源服务器不希望缓存服务器对资源缓存时,最好在 Expires 字段内写 入与首部字段 Date 相同的时间值。

Expires: Wed, 04 Jul 2012 08:26:05 GMT

6.10 Last-Modified

首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个值就是 Request-URI 指定资源被修改的时间。

7 为 Cookie 服务的首部字段

Cookie 的工作机制是用户识别及状态管理。Web 网站为了管理用户的状态会通过 Web 浏览器,把一些数据临时写入用户的计算机内。接着当用户访问该Web网站时,可通过通信方式取回之前发放的 Cookie。

调用 Cookie 时,由于可校验 Cookie 的有效期,以及发送方的域、路径、协议等信息,所以正规发布的 Cookie 内的数据不会因来自其他 Web 站点和攻击者的攻击而泄露。

为 Cookie 服务的首部字段:

首部字段名说明首部类型
Set-Cookie开始状态管理所使用的 Cookie 信息响应首部字段
Cookie服务器接收到的 Cookie 信息请求首部字段

7.1 Set-Cookie

Set-Cookie: status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT; ...

当服务器准备开始管理客户端的状态时,会事先告知各种信息。

Set-Cookie 字段的属性:

属性说明
NAME=VALUE赋予 Cookie 的名称和其值(必需项)
expires=DATECookie 的有效期(若不明确指定则默认为浏览器关闭前为止),服务器端就不存在可以显式删除 Cookie 的方法,但可通过覆盖已过期的 Cookie 实现删除操作
path=PATH将服务器上的文件目录作为 Cookie 的适用对象(若不指定则默认为文档所在的文件目录)
domain=域名作为 Cookie 适用对象的域名(若不指定则默认为创建 Cookie 的服务器的域名),通过 Cookie 的 domain 属性指定的域名可做到与结尾匹配一致
Secure仅在 HTTPS 安全通信时才会发送 Cookie
HttpOnly加以限制,使 Cookie 不能被 JavaScript 脚本访问

7.2 Cookie

Cookie: status=enable

首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。

8 其他首部字段

8.1 X-Frame-Options

X-Frame-Options: DENY

首部字段 X-Frame-Options 属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。

首部字段 X-Frame-Options 有以下两个可指定的字段值。

  • DENY :拒绝
  • SAMEORIGIN :仅同源域名下的页面匹配时许可

8.2 X-XSS-Protection

X-XSS-Protection: 1

首部字段 X-XSS-Protection 属于 HTTP 响应首部,它是针对跨站脚本攻击(XSS)的一种对策,用于控制浏览器 XSS 防护机制的开关。

首部字段 X-XSS-Protection 可指定的字段值如下。

  • 0 :将 XSS 过滤设置成无效状态
  • 1 :将 XSS 过滤设置成有效状态

8.3 DNT

DNT: 1

首部字段 DNT 属于 HTTP 请求首部,其中 DNT 是 Do Not Track 的简称,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方法。

首部字段 DNT 可指定的字段值如下。

  • 0 :同意被追踪
  • 1 :拒绝被追踪

8.4 P3P

P3P: CP="CAO DSP LAW CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa OUR BUS 

首部字段 P3P 属于 HTTP 相应首部,通过利用 P3P(The Platform for Privacy Preferences,在线隐私偏好平台)技术,可以让 Web 网站上的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的目的。