HTTP 报文分两种,一种是请求报文,是浏览器传递给服务器的报文;一种是相应报文,是服务器返回给浏览器的。两种报文的格式略有不同,但都是由两部分构成:
- 报文头,即请求头(请求报文)和响应头(响应报文)。第一行是请求行(请求报文)或者状态行(响应报文)。
- 实体,这个可有也可以不需要。
请求行
请求行由三部分构成:
- 请求方法:是一个动词,如 GET/POST,表示对资源的操作;
- 请求目标:通常是一个 URI,标记了请求方法要操作的资源;
- 版本号:表示报文使用的 HTTP 协议版本。
这三个部分通常使用空格来分隔,最后要用 CRLF 换行表示结束。
状态行
比起请求行来说,状态行要简单一些,同样也是由三部分构成:
- 版本号:表示报文使用的 HTTP 协议版本;
- 状态码:用三位数代码的形式表示处理的结果,比如 200 是成功,500 是服务器错误;
- 原因:作为数字状态码补充,是更详细的解释文字,帮助人理解原因。
报文头字段
请求行或状态行再加上头部字段集合就构成了 HTTP 报文里完整的请求头或响应头。头部字段都是键值对,key 和 value 之间用“:”分隔,最后用 CRLF 换行表示字段结束。
HTTP 头字段非常灵活,不仅可以使用标准里的 Host、Connection 等已有头,也可以任意添加自定义头,这就给 HTTP 协议带来了无限的扩展可能。HTTP 协议规定了非常多的头部字段,实现各种各样的功能,但基本上可以分为四大类:
- 通用字段:在请求头和响应头里都可以出现;
- 请求字段:仅能出现在请求头里,进一步说明请求信息或者额外的附加条件;
- 响应字段:仅能出现在响应头里,补充说明响应报文的信息;
- 实体字段:它实际上属于通用字段,但专门描述 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 后也必须要有空行;
- 请求头由“请求行+头部字段”构成,响应头由“状态行+头部字段”构成;
- 请求行有三部分:请求方法,请求目标和版本号;
- 状态行也有三部分:版本号,状态码和原因字符串;