HTTP 头字段非常灵活,不仅可以使用标准里的 Host、Connection 等已有头,也可以任意添加自定义头,这就给HTTP 协议带来了无限的扩展可能。

使用头字段需要注意下面几点:

  • 字段名不区分大小写,例如“Host”也可以写成“host”,但首字母大写的可读性更好;
  • 字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线“_”。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;
  • 字段名后面必须紧接着“:”,不能有空格,而“:”后的字段值前可以有多个空格;
  • 字段的顺序是没有意义的,可以任意排列不影响语义;
  • 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie。

分类

对 HTTP 报文的解析和处理实际上主要就是对头字段的处理,理解了头字段也就理解了 HTTP 报文

分类

HTTP 协议规定了非常多的头部字段,实现各种各样的功能,但基本上可以分为四大类:

  • 通用字段:在请求头和响应头里都可以出现;
  • 请求字段:仅能出现在请求头里,进一步说明请求信息或者额外的附加条件;
  • 响应字段:仅能出现在响应头里,补充说明响应报文的信息;
  • 实体字段:它实际上属于通用字段,但专门描述 body 的额外信息。

分类

端到端标头

  • 这些标头必须传输到消息的最终接收者:请求的服务器,或响应的客户端。
  • 中间代理必须未经修改地重新传输这些标头,并且缓存必须存储它们。

逐跳报头

  • 这些标头仅对单个传输级连接有意义,并且不得由代理重新传输或缓存。
  • 请注意,只能使用Connection首部设置逐跳首部。

具体

Host字段

作用: 客户端发送请求时,用来指定服务器的域名。有了Host字段,就可以将请求发往「同一台」服务器上的不同网站。

  • 它属于请求字段,只能出现在请求头里,它同时也是唯一一个 HTTP/1.1 规范里要求必须出现的字段,也就是说,如果请求头里没有 Host,那这就是一个错误的报文。
  • Host字段告诉服务器这个请求应该由哪个主机来处理,当一条计算机上托管了多个虚拟主机的时候,服务端就需要用host字段来选择

举个例子,假如在 127.0.0.1 上有三个虚拟主机:“www.chrono.com”“www.metroid.net”和“origin.io”。那么当使用域名的方式访问时,就必须要用 Host字段来区分这三个 IP 相同但域名不同的网站,否则服务器就会找不到合适的虚拟主机,无法处理。

User-Agent字段

  • 请求字段,只出现在请求头里
  • 它使用一个字符串来描述发起HTTP请求的客户端,服务器可以依据它来返回最合适此浏览器显式的页面

但由于历史的原因,User-Agent 非常混乱,每个浏览器都自称是“Mozilla”“Chrome”“Safari”,企图使用这个字段来互相“伪装”,导致 User-Agent 变得越来越长,最终变得毫无意义。

Date字段

  • Date字段是一个通用字段,但通常出现在响应头里,表示HTTP 报文创建的时间
  • 客户端可以使用这个时间再搭配其他字段决定缓存策略。

Server字段

  • Server字段是响应字段,只能出现在响应头里。
  • 它告诉客户端当前正在提供 Web 服务的软件名称和版本号
  • Server 字段也不是必须要出现的,因为这会把服务器的一部分信息暴露给外界,如果这个版本恰好存在 bug,那么黑客就有可能利用 bug 攻陷服务器。所以,有的网站响应头里要么没有这个字段,要么就给出一个完全无关的描述信息。
  • 比如 GitHub,它的 Server 字段里就看不出是使用了Apache 还是 Nginx,只是显示为“GitHub.com”。

Content-Length字段

作用:

  • Content-Length是一个实体消息首部,表示报文里body的长度,也就是请求头或者响应头空行后面数据的长度。 比如:

    • 服务器在返回数据时,带上 Content-Length字段,表明本次回应的数据长度。
    • 服务器看到客户端的请求字段有这个,就知道了后续有多少数据,可以直接接收
    • 如果没有这个字段,那么body就是不定长的,需要使用chunked方式分段传输。

语法:

Content-Length: <length>

举例:

  • 如下图:Content-Length: 1000是告诉浏览器,本次服务器回应的数据长度是 1000 个字节,后面的字节就属于下一个回应了

Content-Type 字段

作用:

  • Content-Type字段用于服务器回应时,告诉客户端,本次数据是什么格式

补充:

  • 客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。

    • 比如:Accept: */*,客户端声明自己可以接受任何格式的数据。

举例:

  • 如下图: Content-Type: text/html; charset=utf-8表明,发送的是网页,而且编码是UTF-8。

Content-Encoding 字段

作用:

  • Content-Encoding 字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。

    • 它实体消息首部,用于对特定媒体类型的数据进行压缩。
    • 当这个首部出现的时候,它的值表示消息主体进行了何种方式的内容编码转换。
    • 这个消息首部用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。
    • 一般建议对数据尽可能地进行压缩,因此才有了这个消息首部的出现。不过对于特定类型的文件来说,比如jpeg图片文件,已经是进行过压缩的了。有时候再次进行额外的压缩无助于负载体积的减小,反而有可能会使其增大。

语法:

Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
Content-Encoding: identity
Content-Encoding: br

补充:

  • 客户端在请求时,用 Accept-Encoding字段说明自己可以接受哪些压缩方法。举例:
Accept-Encoding: gzip, deflate

举例:

  • 如下图, Content-Encoding: gzip表示服务器返回的数据采用了 gzip 方式压缩,告知客户端需要用此方式解压。

使用流程:

  • 客户端可以事先声明一系列的可以支持压缩模式,与请求一齐发送。 Accept-Encoding 这个首部就是用来进行这种内容编码形式协商的:
Accept-Encoding: gzip, deflate
  • 服务器在 Content-Encoding 响应首部提供了实际采用的压缩模式:
Content-Encoding: gzip
  • 需要注意的是,服务器端并不强制要求一定使用何种压缩模式。采用哪种压缩方式高度依赖于服务器端的设置,及其所采用的模块。

Connection字段

作用:

  • Connection 字段最常用于客户端要求服务器使用 TCP 持久连接,以便其他请求复用。
  • Connection 头(header) 决定当前的事务完成后,是否会关闭网络连接。如果该值是“keep-alive”,网络连接就是持久的,不会关闭,使得对同一个服务器的请求可以继续在该连接上完成。
  • 除去标准的逐段传输(hop-by-hop)头(Keep-Alive, Transfer-Encoding, TE, Connection, Trailer, Upgrade (en-US), Proxy-Authorization and Proxy-Authenticate),任何逐段传输头都需要在 Connection 头中列出,这样才能让第一个代理知道必须处理它们且不转发这些头

语法:

Connection: keep-alive
Connection: close
  • close:表明客户端或服务器想要关闭该网络连接,这是HTTP/1.0请求的默认值
  • keep-alive:表明客户端想要保持该网络连接打开,HTTP/1.1的请求默认使用一个持久连接

为什么要引入这个字段:

  • HTTP 是基于 Resquest-Response 形式的,客户端每次发送完一个请求之后,等待服务器响应,最后和服务器断开连接,本次请求结束。
  • 由于 HTTP 是基于TCP/IP传输的,当 HTTP 发送请求的时候要和服务器经过三次握手建立连接,断开的时候要经过四次挥手进行断开。如果有大量的 HTTP 请求的话,每次都要进过 三次握手 和 四次挥手 ,就会非常的耗时。
  • 为了解决这个问题,HTTP引入了keep-alive机制。所谓的 keep-alive 就是客户端和服务器三次握手之后,可以发送多个请求,最后再进行四次挥手。
  • 这样我们就可以节省很多次握手和挥手的步骤,提升了服务器的性能。
  • HTTP 头部中的 connection 就是完成这个功能的,当我们设置 Connection: keep-alive 的时候,就会保持该链接,直到某个请求的 Connection: close 为止。这样可以在很大程度上提高 HTTP 的性能。

举例:

  • Connection: keep-alive表示一个可以复用的 TCP 连接已经建立了,直到客户端或服务器主动关闭连接。

Keep-Alive字段

作用:

  • Keep-Alive是一个通用消息头,允许消息发送者暗示连接的状态,还可以用来设置超时时长和最大请求数。

      • 需要将 Connection 首部的值设置为 “keep-alive” 这个首部才有意义。同时需要注意的是,在HTTP/2 协议中, Connection 和 Keep-Alive 是被忽略的;在其中采用其他机制来进行连接管理。
      • 是逐跳标头,仅对单个传输级别连接有意义,并且不能由代理重新传输或缓存

语法:

Keep-Alive: parameters
  • parameters:一系列用逗号隔开的参数,每一个参数由一个标识符和一个值构成,并使用等号 (‘=’) 隔开。下述标识符是可用的:

    • timeout:指定了一个空闲连接需要保持打开状态的最小时长(以秒为单位)。需要注意的是,如果没有在传输层设置 keep-alive TCP message 的话,大于 TCP 层面的超时设置会被忽略。
    • MAX:在连接关闭之前,在此连接可以发送的请求的最大值。在非管道连接中,除了 0 以外,这个值是被忽略的,因为需要在紧跟着的响应中发送新一次的请求。HTTP 管道连接则可以用它来限制管道的使用。

示例:

Accept-Ranges字段

作用:

  • 该字段表示服务器自身是否支持 范围请求 ,它的值用于表示范围请求的单位。

语法:

Accept-Ranges: bytes
Accept-Ranges: none
  • none:不支持任何范围请求单位,由于其等同于没有返回此头部,因此很少使用。不过一些浏览器,比如IE9,会依据该头部去禁用或者移除下载管理器的暂停按钮。
  • bytes:范围请求的单位是 bytes (字节)。

Content-Range字段

作用:

  • 这个字段是配合 Range 请求使用的,适用于断点续传,下载等功能。
  • 比如在下载的时候,可以使用多个进程,分别下载文件的一部分,到最后合并成一个文件,加快下载速度。

Upgrade字段

作用:

  • 用于将已建立的客户端/服务器连接升级到不同的协议。
  • 注意,如果发送了Upgrade那么就一定要设置Connection: upgrade

语法:

Connection: upgrade
Upgrade: protocol_name[/protocol_version]
  • Connection带有类型的标头upgrade 必须始终与Upgrade标头一起发送
  • 协议之间以逗号分隔
  • 协议按优先级降序排列
  • 协议版本是可选的(以“/”分隔)。例如:
Connection: upgrade
Upgrade: a_protocol/1, example ,another_protocol/2.2

举例:

(1) 客户端可以使用它来将连接从 HTTP 1.1 升级到 HTTP 2.0,或者将 HTTP 或 HTTPS 连接升级为 WebSocket。

  • 注意, Upgrade 仅可以在HTTP/1.1中使用。HTTP/2 明确禁止使用此机制/标头
Connection: Upgrade
Upgrade: websocket

(2)客户端可以使用Upgrade header字段邀请服务器以降序优先顺序切换到列出的一个(或多个)协议。

  • 例如,客户端可能会发送如下请求,列出要切换到的首选协议(在本例中为“example/1”和“foo/2”):
GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: example/1, foo/2
  • 服务器可以出于任何原因选择忽略该请求,在这种情况下,它应该像尚未发送升级头一样进行响应,比如200 OK

  • 如果服务器决定升级连接,它必须:

    • 第一步:响应101 Switching Protocols, 以及Upgrade指定要切换到的协议的标头,比如:
HTTP/1.1 101 Switching Protocols
Upgrade: foo/2
Connection: Upgrade
  • 第二步:使用新协议发送对原始请求的响应

Proxy-Connection

从字面上的意思看,这个字段表示和代理的连接。下面我们来具体看一下

首先我们看一下设置了浏览器代理之后HTTP的请求有哪些变化

GET / HTTP/1.1
Host: www.example.com
Connection: keep-alive
GET http://www.example.com/ HTTP/1.1
Host: www.example.com
Proxy-Connection: keep-alive

我们看到有两个变化

  1. 请求的资源URI变成了完整路径
  2. Connection 头变为了 Proxy-Connection头

为什么需要完整路径

早期的HTTP设计中,浏览器直接和单个服务器对话,不存在虚拟主机。 所以单个服务器总知道自己的主机名和端口,这样浏览器发送请求只需要发送相对地址就可以了。如下:

 GET / HTTP /1.0

有了代理就麻烦了,代理不知道GET / HTTP /1.0 这个请求发给哪个主机,所以HTTP 1.0 又要求浏览器给代理发送的时候必须发送完整的路径名称:

 GET http: //www .example.com/ HTTP /1 .0

HTTP 1.1 规定了必须包含Host主机名这个字段。所以 HTTP 1.1 可以是:

GET / HTTP/1.1Host: www.example.com

但是由于不清楚代理是1.0 还是1.1的 也许代理不认识Host这个头。 所以http 1.1 发给代理的最后格式就变为

GET http://www.example.com/ HTTP/1.1
Host: www.example.com

Accept-Encoding字段

作用:

  • HTTP 请求头 Accept-Encoding 会将客户端能够理解的内容编码方式——通常是某种压缩算法——进行通知(给服务端)。通过内容协商的方式,服务端会选择一个客户端提议的方式,使用并在响应头 Content-Encoding 中通知客户端该选择。

  • 即使客户端和服务器都支持相同的压缩算法,在identity指令可以被接受的情况下,服务器也可以选择对响应主体不进行压缩。导致这种情况出现的两种常见情形是:

    • 要发送的数据已经经过压缩,再次进行压缩不会导致被传输的数据量更小。一些图像格式的文件会存在这种情况
    • 服务器超载,无法承受压缩需求导致的计算开销。通常,如果服务器使用超过80%的计算能力,微软建议不要压缩。
  • 只要 identity —— 表示不需要进行任何编码——没有被明确禁止使用(通过 identity;q=0 指令或是 *;q=0 而没有为 identity 明确指定权重值),则服务器禁止返回表示客户端错误的 406 Not Acceptable 响应。

语法:

Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br
Accept-Encoding: identity
Accept-Encoding: *// Multiple algorithms, weighted with the quality value syntax:
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5

说明:

  • gzip:

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

    • 采用 Lempel-Ziv-Welch (LZW) 压缩算法。这个名称来自UNIX系统的 compress 程序,该程序实现了前述算法。
    • 与其同名程序已经在大部分UNIX发行版中消失一样,这种内容编码方式已经被大部分浏览器弃用,部分因为专利问题(这项专利在2003年到期)。
  • deflate

    • 采用 zlib 结构 (在 RFC 1950 中规定),和 deflate 压缩算法(在 RFC 1951 中规定)。
  • identity

    • 用于指代自身(例如:未经过压缩和修改)。
    • 除非特别指明,这个标记始终可以被接受。
  • br

    • 表示采用 Brotli 算法的编码方式。
  • *

    • 匹配其他任意未在该请求头字段中列出的编码方式。
    • 假如该请求头字段不存在的话,这个值是默认值。
    • 它并不代表任意算法都支持,而仅仅表示算法之间无优先次序
  • ;q= (qvalues weighting)

    • 值代表优先顺序,用相对质量值 表示,又称为权重
    • 相对质量值:由后缀’;q='后紧跟一个介于0和1之间的值来标记

示例

Accept-Encoding: gzip
Accept-Encoding: gzip, compress, br
Accept-Encoding: br;q=1.0, gzip;q=0.8, *;q=0.1

Transfer-Encoding

Transfer-Encoding 消息首部指明了将 实体安全传递给用户所采用的编码形式。

Transfer-Encoding 是一个逐跳传输消息首部,即仅应用于两个节点之间的消息传递,而不是所请求的资源本身。一个多节点连接中的每一段都可以应用不同的Transfer-Encoding 值。如果你想要将压缩后的数据应用于整个连接,那么请使用端到端传输消息首部Content-Encoding

语法

Transfer-Encoding: chunked
Transfer-Encoding: compress
Transfer-Encoding: deflate
Transfer-Encoding: gzip
Transfer-Encoding: identity// Several values can be listed, separated by a comma
Transfer-Encoding: gzip, chunked

chunked

  • 数据以一系列分块的形式进行发送。
  • Content-Length 首部在这种情况下不被发送。
  • 在每一个分块的开头需要添加当前分块的长度,以十六进制的形式表示,后面紧跟着\r\n,之后是分块本身,后面也是\r\n
  • 终止块是一个常规的分块,不同之处在于其长度为0.终止块后面是一个挂载(trailer),由一系列(或者为空)的实体消息首部构成。

示例

分块编码

分块编码主要应用于如下场景,即要传输大量的数据,但是在请求没有被处理完之前响应的长度是无法获得的。例如,当需要用从数据库中查询获得的数据生成一个大的HTML表格的时候,或者需要传输大量的图片的时候。一个分块响应形式如下:

 HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked7\r\n
Mozilla\r\n
9\r\n
Developer\r\n
7\r\n
Network\r\n
0\r\n
\r\n

Trailer字段

Trailer响应头允许发送方在分块消息的末尾包含额外的字段,以提供可能在发送消息体时动态生成的元数据,如消息完整性检查、数字签名或后处理状态。

Note: The TE request header needs to be set to “trailers” to allow trailer fields.

语法

Trailer: header-names

说明:

  • header-names:将出现在HTTP头中分块消息的尾部部分。这些头字段是运行的:

    • 消息帧头(例如,Transfer-EncodingContent-Length),
    • 路由报头(例如,Host),
    • 请求修饰符(如Cache-Control,Max-Forwards,或TE)
    • 认证头(例如,Authorization或Set-Cookie),
    • 或 Content-Encoding, Content-Type, Content-Range和它自己(Trailer)

示例

使用Trailer的分块传输编码

在这个例子中,Expires报头被使用在分块消息的末尾,作为一个尾随报头。

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
Trailer: Expires7\r\n
Mozilla\r\n
9\r\n
Developer\r\n
7\r\n
Network\r\n
0\r\n
Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n
\r\n

抓包

头部字段的:前面和后面可以带有空格吗?

下面是两个最简单的 HTTP 请求,第一个在“:”后有多个空格,第二个在“:”前有空格。

GET /09-1 HTTP/1.1
Host: www.chrono.com
GET /09-1 HTTP/1.1
Host : www.chrono.com

第一个可以正确获取服务器的响应报文,而第二个得到的会是一个“400 Bad Request”,表示请求报文格式有误,服务器无法正确处理:


2
3
HTTP/1.1 400 Bad Request
Server: openresty/1.15.8.1
Connection: close

问题:

(1) 如果拼 HTTP 报文的时候,在头字段后多加了一个CRLF,导致出现了一个空行,会发生什么?

头字段后多了一个CRLF,会被当做body处理

(2) 讲头字段时说“:”后的空格可以有多个,那为什么绝大多数情况下都只使用一个空格呢

节省资源

HTTP:header头总结相关推荐

  1. php header setcookie,php中header头设置Cookie与内置setCookie的区别,和js对cookie操作

    首先声明,浏览的Cookie操作都是通过HTTP Header(俗称"Http头") 来实现.所有的服务器与客户端之间Cookie数据传输都是通过Http请求头来操作. PHP中* ...

  2. curl用法:获取网站的header头及状态码

    curl命令最常用的方法是使用参数-I 获取域名或IP的header信息,包括HTTP返回状态码,server类型,文本类型,缓存时间等等:监控web服务时也常用此方法判断web服务是否正常: 监控w ...

  3. 用php获取header头信息

    研究一晚上php关于自定义header头信息的问题.看了很多代码,但是由于本人才疏学浅.连测试demo都没跑通.实在是惭愧.这里看到个获取header信息的方法,挺不错的,记录一下. 我们可以在$_S ...

  4. 使用 header 头下载文件

    导语 使用 header 头,实现浏览器下载文件.下面是实例代码,更详细的内容查看下方参考资料. 实例 <?php$file = $_GET['file'];// 文件地址是服务器保存路径,如 ...

  5. ajxs跨域 php_php设置header头允许ajax跨域请求

    在做项目的时候,我们有时候希望能够可以跨域进行请求,但是ajax访问php接口的时候,通常会报一个错误: Failed to load 你的网址/test.php: No 'Access-Contro ...

  6. Spring中将header头转换为参数

    项目中遇到一类请求,所有的请求都会将请求参数放在header头中,每个接口都需要单独处理,因此考虑做一层封装,统一进行转换. 基本思路是增加一个拦截器,由拦截器对请求头进行解析,并转换为参数 首先集成 ...

  7. php从头部添加,php如何向header头添加Authorization信息?

    php如何向header头添加Authorization信息? php中,在header头添加Authorization信息需要在curl_exec()方法执行命令前,使用curl_setopt()方 ...

  8. php header apk,php常用的header头

    /** * php常用的header头设置... */ header('HTTP/1.1 200 OK'); // ok 正常访问 header('HTTP/1.1 404 Not Found'); ...

  9. php 跨域 验证_php 前后端分离开发进行跨域请求时ajax发送验证参数token的header头解决方法...

    php前后端分离开发中要实现前后端参数信息交互,必须解决token标识验证问题. 步骤如下: 1.前端ajax发送请求时,要设置一个自定义header头.代码如下: $.ajax({ url:&quo ...

  10. php 获取header头信息并显示网址,php 获取远程网址header头信息的方法

    一个用PHP获取远程网址header头信息的方法,这在采集时很有用,他可以让你判断出来,远程文件或网页是否正常,是否是404页 有二种方法, 1.用php的函数get_headers get_head ...

最新文章

  1. (数据结构与算法)递归及一些经典递归问题
  2. 亚马逊记AWS(Amazon Web Services)自由EC2应用
  3. 机器的速度与主频之间的关系
  4. HDU多校5 - 6816 Boring Game(模拟)
  5. snort的详细配置
  6. 如何让cloudflare缓存html,CloudFlareCDN页面规则缓存设置教程
  7. 华为EMUI 10系统内测截图曝光:基于Android 10.0
  8. spring cloud 学习(6) - zuul 微服务网关
  9. 空军军医大学计算机复试线,2021空军军医大学考研国家线公布时间_国家线是多少分...
  10. 怎么用光驱给服务器装系统,如何用光驱重装系统?
  11. 大数据笔记 | HDFS 常用操作命令
  12. RDKit | RDKit中处理分子Mol对象
  13. 修正Linux下WPS字体库缺失
  14. php页眉,phpword页眉页脚
  15. [转载]三、二、一 …… Geronimo!,第 4 部分: 模式
  16. [C++] 中的trivial destructor
  17. Jqurey总结归纳
  18. h5调用微信,微博等分享
  19. 哪有计算机课程,计算机基础课程的目标有以下哪几个( ? ?)
  20. 用mpx框架自定义小程序底部tabbar

热门文章

  1. 传感器 宽动态范围介绍
  2. vue3使用vue-quill实现富文本编辑器上传图片
  3. 计算机英语论文中英互译,计算机专业中英文文献翻译.doc
  4. 【Unity植物大战僵尸】豌豆射手子弹发射逻辑(十三)
  5. 网站合理使用CDN加速,让你的网站速度飞起来!
  6. mysql ddl导出_ddl语句导出 gp数据库
  7. SVM核函数RBF的参数
  8. Windows电脑设置u盘启动
  9. Linux重要命令-weget
  10. 奈奎斯特准则、比特率、波特率、码元……的逻辑链