HTTP 首部

date
Aug 28, 2022
slug
HTTP-header
status
Published
tags
Network
summary
HTTP 首部
type
Post
Created Time
Oct 28, 2023 01:45 PM
Updated Time
Oct 28, 2023 01:45 PM
AI summary
Status
 
HTTP 协议的请求和响应报文中必定包含 HTTP 首部。根据实际用途,可以被分为 4 种类型。本文主要介绍 HTTP1.1 的首部字段(HTTP/1.1 规范定义了 47 种首部字段)。

通用首部字段(General Header Fields)

请求报文和响应报文两方都会使用的首部。

Cache-Control

通过指定首部字段 Cache-Control 的指令,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。
指令的参数是可选的,多个指令之间通过“,”分隔。首部字段 Cache-Control 的指令可用于请求及响应时。
缓存请求指令
指令
参数
no-cache
no-store
max-age=[秒]
必须
max-stale(=[秒])
可省略
min-fresh=[秒]
必需
no-transform
only-if-cached
cache-extension
-
缓存响应指令
指令
参数
public
private
可省略
no-cache
可省略
no-store
no-transform
must-revalidate
proxy-revalidate
max-age=[秒]
必需
s-maxage=[秒]
必需
cache-extension
-
public 指令
当指定使用 public 指令时,则明确表明其他用户也可以缓存。
private 指令
当指定 private 指令后,缓存服务器只会对特定用户提供资源缓存的服务,对于其他用户发送过来的请求,代理服务器则不会缓存。
no-cache 指令
控制可执行缓存的对象的指令。
使用 no-cache 指令的目的是为了防止从缓存中返回过期的资源。
客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接收缓存过的响应。于是,“中间”的缓存服务器必须把客户端请求转发给源服务器。
如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不会对资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。
由服务器返回的响应中,若报文首部字段 Cache-Control 中对 no-cache 字段名指定了参数值,那么客户端在接收到这个被指定参数值的首部字段对应的响应报文后,就不能使用缓存。换句话说,无参数值的首部字段可以使用缓存。
no-store 指令
当使用 no-store 指令时,暗示请求(和对应的响应)或响应中包含机密信息。因此,缓存不能在本地存储请求或响应的任一部分。
从字面意思上很容易把 no-cache 误解成为不缓存,但事实上 no-cache 代表不缓存过期的资源,缓存会向源服务器进行有效期确认后处理资源,也许称为 do-not-serve-from-cache-without-revalidation 更合适。no-store 才是真正地不进行缓存,请注意区别理解。
s-maxage 指令
s-maxage 指令的功能和 max-age 指令的相同,它们的不同点是 s-maxage 指令只适用于多用户、公共缓存的代理服务器。也就是说,对于同一用户重复返回响应的服务器来说,这个指令没有任何作用。
另外,当使用 s-maxage 指令后,则直接忽略对 Expires 首部字段及 max-age 指令的处理。
max-age 指令
当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓存时间数值比指定时间的数值更小,那么客户端就接收缓存的资源。 另外,当指定 max-age 值为 0,那么缓存服务器通常需要将请求转发给源服务器。
当服务器返回的响应中包含 max-age 指令时,缓存服务器将不对资源的有效性再作确认,而 max-age 数值代表资源保存为缓存的最长时 间。
应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略掉。
min-fresh 指令
min-fresh 指令要求缓存服务器返回至少还未过指定时间的缓存资源。
比如,当指定 min-fresh 为 60 秒后,过了 60 秒的资源都无法作为响应返回了。
max-stale 指令
使用 max-stale 可指示缓存资源,即使过期也照常接收。
如果指令未指定参数值,那么无论经过多久,客户端都会接收响应;如果指令中指定了具体数值,那么即使过期,只要仍处于 max-stale 指定的时间内,仍旧会被客户端接收。
only-if-cached 指令
使用 only-if-cached 指令表示客户端仅在缓存服务器本地缓存目标资源的情况下才会要求其返回。换言之,该指令要求缓存服务器不重新加载响应,也不会再次确认资源有效性。若发生请求缓存服务器的本地缓存无响应,则返回状态码 504 Gateway Timeout。
must-revalidate 指令
使用 must-revalidate 指令,代理会向源服务器再次验证即将返回的响应缓存目前是否仍然有效。
若代理无法连通源服务器再次获取有效资源的话,缓存必须给客户端一条 504(Gateway Timeout)状态码。
另外,使用 must-revalidate 指令会忽略请求的 max-stale 指令(即使已经在首部使用了 max-stale,也不会再有效果)。
proxy-revalidate 指令
proxy-revalidate 指令要求所有的缓存服务器在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性。
no-transform 指令
使用 no-transform 指令规定无论是在请求还是响应中,缓存都不能改变实体主体的媒体类型。
这样做可防止缓存或代理压缩图片等类似操作。
cache-controal 扩展
通过 cache-extension 标记(token),可以扩展 Cache-Control 首部字段内的指令。
如上例,Cache-Control 首部字段本身没有 community 这个指令。借助 extension tokens 实现了该指令的添加。如果缓存服务器不能理解 community 这个新指令,就会直接忽略。因此,extension tokens 仅对能理解它的缓存服务器来说是有意义的。

Connection

决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。
close 指令
HTTP/1.0 请求的默认值,表明客户端或服务器想要关闭该网络连接。
keep-alive 指令
表明客户端想要保持该网络连接打开,HTTP/1.1 的请求默认使用一个持久连接。这个请求头列表由头部名组成,这些头将被第一个非透明的代理或者代理间的缓存所移除:这些头定义了发出者和第一个实体之间的连接,而不是和目的地节点间的连接。

Date

首部字段 Date 表明创建 HTTP 报文的日期和时间。
HTTP/1.1 协议使用在 RFC1123 中规定的日期时间的格式,如下示例:
HTTP/1.1 之前的 HTTP 协议版本中使用在 RFC850 中定义的格式,如下所示:
除此之外,还有一种格式。它与 C 标准库内的 asctime() 函数的输出格式一致:

Pragma

Pragma 是 HTTP/1.1 之前版本的历史遗留字段,仅作为与 HTTP/1.0 的向后兼容而定义。
规范定义的形式唯一,如下所示:
该首部字段属于通用首部字段,但只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。
所有的中间服务器如果都能以 HTTP/1.1 为基准,那直接采用 Cache-Control: no-cache 指定缓存的处理方式是最为理想的。但要整体掌握全部中间服务器使用的 HTTP 协议版本却是不现实的。因此,发送的请求会同时含有下面两个首部字段:

Trailer

Trailer 是一类特殊的首部字段,HTTP 协议在返回数据的时候通常是先发送 Header 信息,再发送 Body 数据,而 Trailer 会在 Body 传输结束后,再将内容“补发”给接收方。
发送方需要事先说明在报文主体后记录了哪些首部字段,可以指定多个,以逗号分隔。
该首部字段可应用在 HTTP/1.1 版本分块传输编码时。
以上用例中,指定首部字段 Trailer 的值为 Expires,在报文主体之后 (分块长度 0 之后)”补发”了首部字段 Expires 中的内容。

Transfer-Encoding

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

Upgrade

首部字段 Upgrade 用于检测 HTTP 协议及其他协议是否可使用更高的 版本进行通信,其参数值可以用来指定一个完全不同的通信协议。
需要注意,Upgrade 首部字段产生作用的 Upgrade 对象仅限于客户端和邻接服务器之间。因此,使用首部字段 Upgrade 时,还需要额外指定 Connection:Upgrade
对于附有首部字段 Upgrade 的请求,服务器可用 101 Switching Protocols 状态码作为响应返回。

Via

使用首部字段 Via 是为了追踪客户端与服务器之间的请求和响应报文的传输路径。
报文经过代理或网关时,会先在首部字段 Via 中附加该服务器的信息,然后再进行转发。这个做法和 traceroute 及电子邮件的 Received 首部的工作机制很类似。
首部字段 Via 不仅用于追踪报文的转发,还可避免请求回环的发生。所以必须在经过代理时附加该首部字段内容。
上述例子中,在经过代理服务器 A 时,Via 首部附加了 1.0 via.jp(Squid/3.1) ,接下来经过代理服务器 B 时亦是如此,当然,B 也可以在保留原 Via 首部的同时,新增一个新的 Via 首部。
Via 首部是为了追踪传输路径,所以经常会和 TRACE 方法一起使用。比如,代理服务器接收到由 TRACE 方法发送过来的请求(其中 Max-Forwards: 0)时,代理服务器就不能再转发该请求了。这种情况下,代理服务器会将自身的信息附加到 Via 首部后,返回该请求的响应。

Warning

HTTP/1.1 的 Warning 首部是从 HTTP/1.0 的响应首部(Retry-After)演 变过来的。该首部通常会告知用户一些与缓存相关的问题的警告。
Warning 首部的格式如下。最后的日期时间部分可省略。
HTTP/1.1 中定义了 7 种警告。警告码对应的警告内容仅推荐参考。 另外,警告码具备扩展性,今后有可能追加新的警告码。
警告码
警告内容
说明
110
Response is stale
由缓存服务器提供的响应已过期(设置的失效时间已过)
111
Revalidation Failed
由于无法访问服务器,重复验证失败
112
Disconnected Operation
代理服务器断开连接。
113
Heuristic Expiration
响应的使用期超过24小时(有效缓存的设定时间大于24小时的情况下)
199
Miscellaneous Warning
任意的、未明确指定的警告信息
214
Transformation Applied
由代理服务器添加,如果它对返回的展现内容进行了任何转换,比如改变了内容编码、媒体类型等。
299
Miscellaneous persistent Warning
与 199 类似,只不过指代的是持久化警告

请求首部字段(Request Header Fields)

请求首部字段是从客户端往服务器端发送请求报文中所使用的字段,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等内容。

Accept

Accept 首部字段可通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可使用 type/subtype 这种形式,一次指定多种媒体类型。
若想要给显示的媒体类型增加优先级,则使用 q= 来额外表示权重值,用分号(;)进行分隔。权重值 q 的范围是 0~1(可精确到小数点后 3 位),且 1 为最大值。不指定权重 q 值时,默认权重为 q=1.0。
当服务器提供多种内容时,将会首先返回权重值最高的媒体类型。

Accept-Charset

Accept-Charset 首部字段可用来通知服务器用户代理支持的字符集及字符集的相对优先顺序。另外,可一次性指定多种字符集。与首部字段 Accept 相同的是可用权重 q 值来表示相对优先级。
该首部字段应用于内容协商机制的服务器驱动协商。

Accept-Encoding

Accept-Encoding 首部字段用来告知服务器用户代理支持的内容编码及内容编码的优先级顺序。可一次性指定多种内容编码。
  • gzip : 由文件压缩程序 gzip(GNU zip)生成的编码格式 (RFC1952),采用 Lempel-Ziv 算法(LZ77)及 32 位循环冗余 校验(Cyclic Redundancy Check,通称 CRC)。
  • compress : 由 UNIX 文件压缩程序 compress 生成的编码格式,采用 Lempel- Ziv-Welch 算法(LZW)。
  • deflate : 组合使用 zlib 格式(RFC1950)及由 deflate 压缩算法 (RFC1951)生成的编码格式。
  • identity : 不执行压缩或不会变化的默认编码格式。
采用权重 q 值来表示相对优先级,这点与首部字段 Accept 相同。另外,也可使用星号(*)作为通配符,指定任意的编码格式。

Accept-Language

首部字段 Accept-Language 用来告知服务器用户代理能够处理的自然语言集(指中文或英文等),以及自然语言集的相对优先级。可一次指定多种自然语言集。
和 Accept 首部字段一样,按权重值 q 来表示相对优先级。在上例中,客户端在服务器有中文版资源的情况下,会请求其返回中文版对应的响应,没有中文版时,则请求返回英文版响应。

Authorization

首部字段 Authorization 是用来告知服务器,用户代理的认证信息(证书值)。通常,想要通过服务器认证的用户代理会在接收到返回的 401 状态码响应后,把首部字段 Authorization 加入请求中。共用缓存在接收到含有 Authorization 首部字段的请求时的操作处理会略有差异(可参阅 RFC2616)。

Expect

Expect 是一个请求消息头,包含一个期望条件,表示服务器只有在满足此期望条件的情况下才能妥善地处理请求。
规范中只规定了一个期望条件,即 Expect: 100-continue, 对此服务器可以做出如下回应:
  • 100 如果消息头中的期望条件可以得到满足,使得请求可以顺利进行的话,
  • 417 (Expectation Failed) 如果服务器不能满足期望条件的话;也可以是其他任意表示客户端错误的状态码(4xx)。

From

首部字段 From 用来告知服务器使用用户代理的用户的电子邮件地址。通常,其使用目的就是为了显示搜索引擎等用户代理的负责人的电子邮件联系方式。使用代理时,应尽可能包含 From 首部字段(但可能会因代理不同,将电子邮件地址记录在 User-Agent 首部字段内)。

Host

Host 请求头指明了请求将要发送到的服务器主机名和端口号,Host 会告知服务器,请求的资源所处的互联网主机名和端口号。Host 首部字段在 HTTP/1.1 规范内是唯一一个必须被包含在请求内的首部字段,否则会收到 400 状态码。
首部字段 Host 和以单台服务器分配多个域名的虚拟主机的工作机制有很密切的关联,这是首部字段 Host 必须存在的意义。
请求被发送至服务器时,请求中的主机名会用 IP 地址直接替换解决。但如果这时,相同的 IP 地址下部署运行着多个域名,那么服务器就会无法理解究竟是哪个域名对应的请求。因此,就需要使用首部 字段 Host 来明确指出请求的主机名。若服务器未设定主机名,那直接发送一个空值即可。如下所示。

If-Match

请求首部 If-Match 的使用表示这是一个条件请求。在请求方法为 GET 和 HEAD 的情况下,服务器仅在请求的资源满足此首部列出的 ETag 值时才会返回资源。而对于 PUT 或其他非安全方法来说,只有在满足条件的情况下才可以将资源上传。
首部字段 If-Match,属附带条件之一,它会告知服务器匹配资源所用的实体标记(ETag)值。这时的服务器无法使用弱 ETag 值。
服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响应。
还可以使用星号(*)指定 If-Match 的字段值。针对这种情况,服务器将会忽略 ETag 的值,只要资源存在就处理请求。

If-Modified-Since

首部字段 If-Modified-Since,属附带条件之一,它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源都没有过更新,则返回状态码 304 Not Modified 的响应。
If-Modified-Since 用于确认代理或客户端拥有的本地资源的有效性。获取资源的更新日期时间,可通过确认首部字段 Last-Modified 来确定。

If-None-Match

If-None-Match 是一个条件式请求首部。它和首部字段 If-Match 作用相反。对于 GET 和 HEAD 请求方法来说,当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的相匹配的时候,服务器端才会返回所请求的资源,响应码为 200 。对于其他方法来说,当且仅当最终确认没有已存在的资源的 ETag 属性值与这个首部中所列出的相匹配的时候,才会对请求进行相应的处理。
对于 GET 和 HEAD 方法来说,当验证失败的时候,服务器端必须返回响应码 304(Not Modified,未改变)。对于能够引发服务器状态改变的方法,则返回 412(Precondition Failed,前置条件失败)。需要注意的是,服务器端在生成状态码为 304 的响应的时候,必须同时生成以下会存在于对应的 200 响应中的首部:Cache-Control、Content-Location、Date、ETag、Expires 和 Vary 。
ETag 属性之间的比较采用的是弱比较算法,即两个文件除了每个字节都相同外,内容一致也可以认为是相同的。例如,如果两个页面仅仅在页脚的生成时间有所不同,就可以认为二者是相同的。
当与 If-Modified-Since 一同使用的时候,If-None-Match 优先级更高(假如服务器支持的话)。
以下是两个常见的应用场景:
  • 采用 GET 或 HEAD 方法,来更新拥有特定的ETag 属性值的缓存。
  • 采用其他方法,尤其是 PUT,将 If-None-Match used 的值设置为 * ,用来生成事先并不知道是否存在的文件,可以确保先前并没有进行过类似的上传操作,防止之前操作数据的丢失。这个问题属于更新丢失问题的一种。

If-Range

If-Range HTTP 请求头字段用来使得 Range 头字段在一定条件下起作用:当字段值中的条件得到满足时,Range 头字段才会起作用,同时服务器回复206 部分内容状态码,以及Range 头字段请求的相应部分;如果字段值中的条件没有得到满足,服务器将会返回 200 OK 状态码,并返回完整的请求资源。
字段值中既可以用 Last-Modified 时间值用作验证,也可以用ETag标记作为验证,但不能将两者同时使用。
If-Range 头字段通常用于断点续传的下载过程中,用来自从上次中断后,确保下载的资源没有发生改变。

If-Unmodified-Since

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

Max-Forwards

Max-Forwards 是一个通用报文首部,在 Trace 或 Options 方法中,该字段以十进制整数形式指定可经过的服务器最大数目。服务器在往下一个服务器转发请求之前,Max-Forwards 的值减 1 后重新赋值。当服务器接收到 Max-Forwards 值为 0 的请求时,则不再进行转发,而是直接返回响应。
使用 HTTP 协议通信时,请求可能会经过代理等多台服务器。途中,如果代理服务器由于某些原因导致请求转发失败,或者由于未知原因,导致请求陷入代理之间的循环,客户端也就等不到服务器返回的响应了。此时,可以灵活使用首部字段 Max-Forwards,针对以上问题产生的原因展开调查。由于当 Max-Forwards 字段值为 0 时,服务器就会立即返回响应,由此我们至少可以对以那台服务器为终点的传输路径的通信状况有所把握。

Proxy-Authorization

接收到从代理服务器发来的认证质询时,客户端会发送包含首部字段 Proxy-Authorization 的请求,以告知服务器认证所需要的信息。
这个行为是与客户端和服务器之间的 HTTP 访问认证相类似的,不同之处在于,认证行为发生在客户端与代理之间。客户端与服务器之间的认证,使用首部字段 Authorization 可起到相同作用。
Proxy-Authenticate 首部需要与 Proxy Authentication Required 响应一起发送。

Range

对于只需获取部分资源的范围请求,设置首部字段 Range 即可告知服务器资源的指定范围。上面的示例表示请求获取从第 5001 字节至第 10000 字节的资源。
接收到附带 Range 首部字段请求的服务器,会在处理请求之后返回状态码为 206 Partial Content 的响应。假如所请求的范围不合法,那么服务器会返回 416 Range Not Satisfiable 状态码,表示客户端错误。无法处理该范围请求时,则会返回状态码 200 OK 的响应及全部资源。

Referer

Referer 请求头包含了当前请求页面的来源页面的地址,即表示当前页面是通过此来源页面里的链接进入的。服务端一般使用 Referer 请求头识别访问来源,可能会以此进行统计分析、日志记录以及缓存优化等。
客户端一般都会发送 Referer 首部字段给服务器。但当直接在浏览器的地址栏输入 URI,或出于安全性的考虑时,也可以不发送该首部字段。因为原始资源的 URI 中的查询字符串可能含有 ID 和密码等保密信息,写进 Referer 转发给其他服务器,则有可能导致保密信息的泄露。
需要注意的是 referer 实际上是 "referrer" 误拼写。
在以下两种情况下,Referer 不会被发送:
  • 来源页面采用的协议为表示本地文件的 "file" 或者 "data" URI;
  • 当前请求页面采用的是非安全协议,而来源页面采用的是安全协议(HTTPS)。

TE

TE 请求型头部用来指定用户代理希望使用的传输编码类型。(可以将其非正式称为 Accept-Transfer-Encoding, 这个名称显得更直观一些)。
它和首部字段 Accept-Encoding 的功能很相像,但是用于传输编码。首部字段 TE 除指定传输编码之外,还可以指定伴随 trailer 字段的分块传输编码的方式。应用后者时,只需把 trailers 赋值给该字段值。值得注意的是, 支持 HTTP/1.1 协议的接收方一定可以处理 chunked 传输编码请求,所以没有必要一定在 TE 首部指定"chunked"关键字。然而,如果客户端将要接收编码在 chunked 包体里面的"trailer"信息的时候,主动指定该头部将会非常有用。

User-Agent

User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。
由网络爬虫发起请求时,有可能会在字段内添加爬虫作者的电子邮件地址。此外,如果请求经过代理,那么中间也很可能被添加上代理服务器的名称。

响应首部字段(Response Header Fields)

响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息,以及对客户端的附加要求等信息。

Accept-Ranges

服务器使用 HTTP 响应头 Accept-Ranges 标识自身支持范围请求 (partial requests)。字段的具体值用于定义范围请求的单位,用于指定能够获取服务器端某个部分的资源。
当浏览器发现Accept-Ranges头时,可以尝试继续中断下载,而不是重新开始。
可指定的字段值有两种,可处理范围请求时指定其为 bytes,反之则 指定其为 none。
  • none: 不支持任何范围请求单位,由于其等同于没有返回此头部,因此很少使用。不过一些浏览器,比如 IE9,会依据该头部去禁用或者移除下载管理器的暂停按钮。
  • bytes: 范围请求的单位是 bytes(字节)。

Age

首部字段 Age 能告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。
若创建该响应的服务器是缓存服务器,Age 值是指缓存后的响应再次发起认证到认证完成的时间值。代理创建响应时必须加上首部字段 Age。
Age 的值通常接近于 0。表示此对象刚刚从原始服务器获取不久;其他的值则是表示代理服务器当前的系统时间与此应答中的通用头 Date 的值之差。

ETag

首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。
另外,当资源更新时,ETag 值也需要更新。Etags 类似于指纹,生成 ETag 值时,并没有统一的算法规则,由服务器来决定。比较 etags 能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。
ETag 中有强 ETag 值和弱 ETag 值之分:
  • 强 ETag 值:不论实体发生多么细微的变化都会改变其值。
    • 弱 ETag 值:弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。
       

      Location

      Location 首部指定的是需要将页面重新定向至的地址。一般在响应码为 3xx 的响应中才会有意义。
      发送新请求,获取 Location 指向的新页面所采用的方法与初始请求使用的方法以及重定向的类型相关:
      • 303 (See Also) 始终引致请求使用 GET 方法,而,而 307 (Temporary Redirect) 和 308 (Permanent Redirect) 则不转变初始请求中的所使用的方法;
      • 301 (Permanent Redirect) 和 302 (Found) 在大多数情况下不会转变初始请求中的方法,不过一些比较早的用户代理可能会引发方法的变更(所以你基本上不知道这一点)。
      状态码为上述之一的所有响应都会带有一个 Location 首部。
      除了重定向响应之外, 状态码为 201 (Created) 的消息也会带有 Location 首部。它指向的是新创建的资源的地址。
      Location 与 Content-Location是不同的,前者(Location )指定的是一个重定向请求的目的地址(或者新创建的文件的 URL),而后者( Content-Location)指向的是经过内容协商后的资源的直接地址,不需要进行进一步的内容协商。Location 对应的是响应,而 Content-Location 对应的是要返回的实体。

      Proxy-Authenticate

      首部字段 Proxy-Authenticate 会把由代理服务器所要求的认证信息发送给客户端。
      Proxy-Authenticate 首部需要与 407 Proxy Authentication Required 响应一起发送。
      它与客户端和服务器之间的 HTTP 访问认证的行为相似,不同之处在 于其认证行为是在客户端与代理之间进行的。而客户端与服务器之间 进行认证时,首部字段 WWW-Authorization 有着相同的作用。

      Retry-After

      首部字段 Retry-After 告知客户端应该在多久之后再次发送请求。主要 配合状态码 503 Service Unavailable 响应,或 3xx Redirect 响应一起使用。
      • 当与 503 (Service Unavailable,当前服务不存在) 响应一起发送的时候,表示服务下线的预期时长。
      • 当与重定向响应一起发送的时候,比如 301 (Moved Permanently,永久迁移),表示用户代理在发送重定向请求之前需要等待的最短时间。
      字段值可以指定为具体的日期时间(Wed, 04 Jul 2012 06:34:24 GMT 等格式),也可以是创建响应后的秒数。

      Server

      首部字段 Server 告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。不单单会标出服务器上的软件应用名称,还有可能包括版本号和安装时启用的可选项。
      应该避免使用过长或者过于详细的描述作为 Server 的值,因为这有可能泄露服务器的内部实现细节,有利于攻击者找到或者探测已知的安全漏洞。

      Vary

      Vary 是一个 HTTP 响应头部信息,它决定了对于未来的一个请求头,应该缓存中的数据 (response) 还是向源服务器请求一个新的数据。它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers)。
      在响应状态码为 304 Not Modified 的响应中,也要设置 Vary 首部,而且要与相应的 200 OK 响应设置得一模一样。
      从代理服务器接收到源服务器返回包含 Vary 指定项的响应之后,若要进行缓存,仅对请求中含有相同 Vary 指定首部字段的请求返回缓存。即使对相同资源发起请求,如果 Vary 指定的首部字段不相同,也必须要从源服务器重新获取资源。

      WWW-Authenticate

      HTTP WWW-Authenticate 响应头定义了使用何种验证方式去获取对资源的连接。
      WWW-Authenticate header 通常会和一个 401 Unauthorized 的响应一同被发送。
      上述示例中,realm 字段的字符串是为了辨别请求 URI 指定资源所受 到的保护策略。

      实体首部字段(Entity Header Fields)

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

      Allow

      首部字段 Allow 用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。
       
      如果 Allow 首部字段的值为空,说明资源不接受使用任何 HTTP 方法的请求。这是可能的,比如服务器需要临时禁止对资源的任何访问。

      Content-Encoding

      首部字段 Content-Encoding 列出了对当前实体消息(消息荷载)应用的任何编码类型,以及编码的顺序。它让接收者知道需要以何种顺序解码该实体消息才能获得原始荷载格式。 Content-Encoding 主要用于在不丢失原媒体类型内容的情况下压缩消息数据。
      主要采用以下 4 种内容编码的方式:gzi、compress、deflate、identify。
      请注意原始媒体/内容的类型通过 Content-Type 首部给出,而 Content-Encoding 应用于数据的表示,或"编码形式"。如果原始媒体以某种方式编码(例如 zip 文件),则该信息不应该被包含在 Content-Encoding 首部内。
      一般建议服务器应对数据尽可能地进行压缩,并在适当情况下对内容进行编码。对一种压缩过的媒体类型如 zip 或 jpeg 进行额外的压缩并不合适,因为这反而有可能会使荷载增大。

      Content-Language

      Content-Language 是一个实体消息首部,用来说明访问者希望采用的语言或语言组合,这样的话用户就可以根据自己偏好的语言来定制不同的内容。
      如果没有指明 Content-Language,那么默认地,文件内容是提供给所有语言的访问者使用的。多个语言标签也是合法的,同样的,这个首部还可以用来描述不同媒体类型的文件,而不单单局限于文本型文档。

      Content-Length

      Content-Length 是一个实体消息首部,用来指明发送给接收方的消息主体的大小,即用十进制数字表示的八位元组的数目。

      Content-Location

      首部字段 Content-Location 给出与报文主体部分相对应的 URI。和首部字段 Location 不同(指定的是一个重定向请求的目的地址 URL),Content-Location 表示的是报文主体返回资源对应的 URI。
      对于使用首部字段 Accept-Language 的服务器驱动型请求,当返回的页面内容与实际请求的对象不同时,首部字段 Content-Location 内会写明 URI。

      Content-MD5

      首部字段 Content-MD5 是一串由 MD5 算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。
      对报文主体执行 MD5 算法获得的 128 位二进制数,再通过 Base64 编码后将结果写入 Content-MD5 字段值。由于 HTTP 首部无法记录二进制值,所以要通过 Base64 编码处理。为确保报文的有效性,作为接收方的客户端会对报文主体再执行一次相同的 MD5 算法。计算出的值与字段值作比较后,即可判断出报文主体的准确性。
      采用这种方法,对内容上的偶发性改变是无从查证的,也无法检测出恶意篡改。其中一个原因在于,内容如果能够被篡改,那么同时意味着 Content-MD5 也可重新计算然后被篡改。所以处在接收阶段的客户端是无法意识到报文主体以及首部字段 Content-MD5 是已经被篡改过的。

      Content-Range

      在 HTTP 协议中,响应首部 Content-Range 显示的是一个数据片段在整个文件中的位置及整个实体的大小。

      Content-Type

      首部字段 Content-Type 说明了实体主体内对象的媒体类型。和首部字段 Accept 一样,字段值用 type/subtype 形式赋值。
      参数 charset 使用 iso-8859-1 或 euc-jp 等字符集进行赋值。
      在响应中,Content-Type 标头告诉客户端实际返回的内容的内容类型。浏览器会在某些情况下进行 类型查找,结果并不一定遵循此标题的值;为了防止这种行为,可以将标题 X-Content-Type-Options 设置为 nosniff。

      Expires

      首部字段 Expires 会将资源失效的日期告知客户端。缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
      无效的日期,比如 0,代表着过去的日期,即该资源已经过期。
      源服务器不希望缓存服务器对资源缓存时,最好在 Expires 字段内写入与首部字段 Date 相同的时间值。
      如果在 Cache-Control 响应头设置了 "max-age" 或者 "s-max-age" 指令,那么 Expires 头会被忽略。

      Last-Modified

      首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个值就是 Request-URI 指定资源被修改的时间。但类似使用 CGI 脚本进行动态数据处理时,该值有可能会变成数据最终修改时的时间。它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段。

      Cookie

      管理服务器与客户端之间状态的 Cookie,虽然没有被编入标准化 HTTP/1.1 的 RFC2616 中,但在 Web 网站方面得到了广泛的应用。
      Cookie 的工作机制是用户识别及状态管理。Web 网站为了管理用户的状态会通过 Web 浏览器,把一些数据临时写入用户的计算机内。当用户访问该 Web 网站时,可通过通信方式取回之前发放的 Cookie。
      调用 Cookie 时,由于可校验 Cookie 的有效期,以及发送方的域、路径、协议等信息,所以正规发布的 Cookie 内的数据不会因来自其他 Web 站点和攻击者的攻击而泄露。
      网景通信公司设计并开发了 Cookie,并制定相关的规格标准。1994 年前后,Cookie 正式应用在网景浏览器中。目前最为普及的 Cookie 方式也是以此为基准的。

      Set-Cookie

      Set-Cookie 是响应首部字段,当服务器准备开始管理客户端的状态时,会事先告知各种信息。
      Set-Cookie 包含很多字段值,下面,我们来一一进行介绍。
      expires 属性
      Cookie 的 expires 属性指定浏览器可发送 Cookie 的有效期。
      当省略 expires 属性时,其有效期仅限于维持浏览器会话(Session) 时间段内。这通常限于浏览器应用程序被关闭之前。
      另外,一旦 Cookie 从服务器端发送至客户端,服务器端就不存在可以显式删除 Cookie 的方法。但可通过覆盖已过期的 Cookie,实现对客户端 Cookie 的实质性删除操作。
      path 属性
      Cookie 的 path 属性可用于限制指定 Cookie 的发送范围的文件目录。 不过另有办法可避开这项限制,因此,不能用其作为安全机制。
      domain 属性
      通过 Cookie 的 domain 属性指定的域名可做到与结尾匹配一致。比如,当指定 example.com 后,除 example.com 以外,www.example.comwww2.example.com 等都可以发送 Cookie。
      因此,除了针对具体指定的多个域名发送 Cookie 之 外,不指定 domain 属性显得更安全。
      secure 属性
      Cookie 的 secure 属性用于限制 Web 页面仅在 HTTPS 安全连接时,才可以发送 Cookie。
      发送 Cookie 时,指定 secure 属性的方法如下所示。
      以上例子仅当在 https://www.example.com/(HTTPS)安全连接的情况下才会进行 Cookie 的回收。也就是说,即使域名相同, http://www.example.com/(HTTP)也不会发生 Cookie 回收行为。
      当省略 secure 属性时,不论 HTTP 还是 HTTPS,都会对 Cookie 进行 回收。
      HttpOnly 属性
      Cookie 的 HttpOnly 属性是 Cookie 的扩展功能,它使 JavaScript 脚本无法获得 Cookie。其主要目的为防止跨站脚本攻击(Cross-site scripting,XSS)对 Cookie 的信息窃取。
      发送指定 HttpOnly 属性的 Cookie 的方法如下所示。
      通过上述设置,通常从 Web 页面内还可以对 Cookie 进行读取操作。 但使用 JavaScript 的 document.cookie 就无法读取附加 HttpOnly 属性后的 Cookie 的内容了。因此,也就无法在 XSS 中利用 JavaScript 劫持 Cookie 了。
      虽然是独立的扩展功能,但 Internet Explorer 6 SP1 以上版本等当下的主流浏览器都已经支持该扩展了。另外顺带一提,该扩展并非是为了防止 XSS 而开发的。

      Cookie

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

      其他首部字段

      HTTP 首部字段是可以自行扩展的。所以在 Web 服务器和浏览器的应用上,会出现各种非标准的首部字段。
      接下来,我们就一些最为常用的首部字段进行说明。

      X-Frame-Options

      首部字段 X-Frame-Options 属于 HTTP 响应首部,用于控制网站内容在其他 Web 网站的 Frame 标签内的显示问题。其主要目的是为了防止点击劫持(clickjacking)攻击。
      首部字段 X-Frame-Options 有以下两个可指定的字段值:
      • DENY:拒绝
      • SAMEORIGIN:仅同源域名下的页面(Top-level-browsing- context)匹配时许可。(比如,当指定 http://hacker.com/sample.html 页面为 SAMEORIGIN 时,那么 hacker.com 上所有页面的 frame 都被允许可加载该页面,而 example.com 等其他域名的页面就不行了)
      现在主流的浏览器都已经支持该首部字段。

      X-XSS-Protection

      首部字段 X-XSS-Protection 属于 HTTP 响应首部,它是针对跨站脚本攻击(XSS)的一种对策,用于控制浏览器 XSS 防护机制的开关。
      首部字段 X-XSS-Protection 可指定的字段值如下:
      • 0:将 XSS 过滤设置成无效状态
      • 1:将 XSS 过滤设置成有效状态

      DNT

      首部字段 DNT 属于 HTTP 请求首部,其中 DNT 是 Do Not Track 的简称,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方法。
      首部字段 DNT 可指定的字段值如下。
      • 0:同意被追踪
      • 1:拒接被追踪
      由于首部字段 DNT 的功能具备有效性,所以 Web 服务器需要对 DNT 做对应的支持。

      P3P

      首部字段 P3P 属于 HTTP 相应首部,通过利用 P3P(The Platform for Privacy Preferences,在线隐私偏好平台)技术,可以让 Web 网站上的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的目的。
      要进行 P3P 的设定,需按以下操作步骤进行:
      1. 创建 P3P 隐私;
      1. 创建 P3P 隐私对照文件后,保存命名在 /w3c/p3p.xml 中;
      1. 从 P3P 隐私中新建 Compact policies 后,输出到 HTTP 响应中。
      有关 P3P 的详细规范标准参考这个链接

      你应该知道的事情

      当 HTTP 报文首部中出现了两个或两个以上具有相同首部字段名时会怎么样?

      这种情况在规范内尚未明确,根据浏览器内部处理逻辑的不同,结果可能并不一致。有些浏览器会默认使用第一次出现的首部字段,而有些浏览器使用最后出现的首部字段。

      协议中对 X- 前缀的废除

      在 HTTP 等多种协议中,通过给非标准参数加上前缀 X-,来区别于标准参数,并使那些非标准的参数作为扩展变成可能。但是这种简单粗暴的做法有百害而无一益,因此在“RFC 6648 - Deprecating the "X-" Prefix and Similar Constructs in Application Protocols"中提议停止该做法。
      然而,对已经在使用中的 X- 前缀来说,不应该要求其变更。

      © 孙东辉 2022 - 2024