HTTP 报文分两种,一种是请求报文,是浏览器传递给服务器的报文;一种是相应报文,是服务器返回给浏览器的。两种报文的格式略有不同,但都是由两部分构成:

  • 报文头,即请求头(请求报文)和响应头(响应报文)。第一行是请求行(请求报文)或者状态行(响应报文)。
  • 实体,这个可有也可以不需要。

请求行

请求行由三部分构成:

  1. 请求方法:是一个动词,如 GET/POST,表示对资源的操作;
  2. 请求目标:通常是一个 URI,标记了请求方法要操作的资源;
  3. 版本号:表示报文使用的 HTTP 协议版本。

这三个部分通常使用空格来分隔,最后要用 CRLF 换行表示结束。

状态行

比起请求行来说,状态行要简单一些,同样也是由三部分构成:

  1. 版本号:表示报文使用的 HTTP 协议版本;
  2. 状态码:用三位数代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;
  3. 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。

报文头字段

请求行或状态行再加上头部字段集合就构成了 HTTP 报文里完整的请求头或响应头。头部字段都是键值对,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字段结束。

HTTP 头字段非常灵活,不仅可以使用标准里的 Host、Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。HTTP 协议规定了非常多的头部字段,实现各种各样的功能,但基本上可以分为四大类:

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

Host

它属于请求字段,只能出现在请求头里,也是唯一一个 HTTP/1.1 规范里要求必须出现的字段。如果请求头里没有 Host,那这就是一个错误的报文。

User-Agent

User-Agent是请求字段,只出现在请求头里,用于表明客户端的类型。不过大家都相互伪装,导致这个字段非常混乱。

Date

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

Server

Server字段是响应字段,只能出现在响应头里。它告诉客户端当前正在提供 Web 服务的软件名称和版本号。

Content-Length

Content-Length是实体字段,它表示报文里 body 的长度,服务器看到这个字段,就知道了后续有多少数据,可以直接接收。如果没有这个字段,那么 body 就是不定长的,需要使用 chunked 方式分段传输。

总结

  • HTTP 报文结构由“头部+空行+实体”组成,简单地说就是“header+body“;
  • HTTP 报文可以没有 body,但必须要有 header,而且 header 后也必须要有空行;
  • 请求头由“请求行+头部字段”构成,响应头由“状态行+头部字段”构成;
  • 请求行有三部分:请求方法,请求目标和版本号;
  • 状态行也有三部分:版本号,状态码和原因字符串;