HTTP (HyperText Transfer Protocol)即超文本传输协议是互联网上应用最为广泛的一种网络协议,也是比较基础协议。作为开发者,我们有必要掌握HTTP协议以及背后的技术细节。
变迁
HTTP/0.9
HTTP于1990年问世,那时候并没有建立正式的HTTP标准,之所以被称为HTTP/0.9,是因为它含有HTTP/1.0之前版本的意思。该版本也极其简单,只有一个命令GET,同时协议规定,服务器只能响应HTML格式的字符串,不能响应别的格式。服务器发送完毕后,就会关闭TCP连接。HTTP/1.0
1996年5月,HTTP/1.0 版本发布。该版本增加了大量的新特性。在原来GET命令的基础上,引入了POST命令、HEAD命令。同时对传输内容放开了限制使得任何格式的内容都可以发送,大大丰富了互联网的内容。同时规范了HTTP请求和回应的格式,规定请求和响应的内容需要包括头和体。HTTP/1.1
1997年1月,HTTP/1.1 版本发布。进一步完善了 HTTP 协议,该版本也是HTTP主流的协议版本。该版本引入了持久连接,TCP连接默认不关闭,可以被多个请求复用,而不用声明Connection请求头。HTTP/2
2015年,HTTP/2 发布。该版本的HTTP引用了大量的新特性,同时对原来的HTTP做了许多变革。HTTP/2 彻底二进制化,头信息和数据体都是二进制,这些二进制统称为帧,包含头信息帧和数据帧。HTTP/2 可以在一个连接里同时发送多个请求或响应,而且不用按照顺序一一对应,不用担心请求拥塞。HTTP/2 引入了头信息压缩机制,来降低每次请求与响应的带宽。HTTP/2 引入了服务器推送,允许服务器未经请求,主动向客户端发送数据。
HTTP 报文
用于HTTP交互的信息成为HTTP报文,请求端的报文成为请求报文,响应端的报文叫做响应报文。HTTP报文是由多行数据构成的字符串文本,并由CR+LF作为换行符。这里分析的HTTP协议依然是HTTP/1.1版本,该版本是目前使用得最广泛的协议。
1、请求报文
请求报文主要分为请求行、请求首部(header)、body(请求体)。header 和 body 空行( CR为回车符,LF换行符 )。以下CRLF均表示回车加换行。
请求报文抓包:
GET / HTTP/1.1
Host: www.jianshu.com
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest
-
请求行
请求行包含了请求的方式(GET、POST、HEAD等),请求的URI以及HTTP协议的版本。
请求方式 空格 请求URI HTTP版本 CRLF
请求行实例:
GET / HTTP/1.1
GET、POST 请求参数附加在URL上的时候,在HTTP发送请求报文的时候会将URL的请求参数放入请求行,如请求 http://www.jianshu.com/?name=iOS&age=10,这里我们加入了name和age两个参数,抓包如下:
可见这时请求行为:
GET /?name=iOS&age=10 HTTP/1.1
-
请求首部
请求首部本质就是键值对,是构成HTTP报文的要素之一,它能起到传递额外信息的作用,它的格式如下:
Key: 空格 value CRLF
以下是对的请求报文:
GET /?name=iOS&age=10 HTTP/1.1
name: iOS
Cookie: signin_redirect=http%3A%2F%2Fwww.jianshu.com%2F%3Fname%3DiOS%26age%3D10; _maleskine_session=SGhIVENaem04NWVWSE5UMkVGNWFUTGZSR0hlT2J0dUgyWGJ1bFlMS2h6Smx0UnZ0Mk9tR25zWTBubWJZZmU2UkhUT2RMQ3ZZT0lTQ2U2d3NaVDR3TnBTQ1kwcXgyZHJnNkxsSkI3Q0lFYkxkY0xlbzA1Q1Z2MmRIa1RzNkliQnBFMzJQUmRIeXY3MXI0Wk1zZjd2eGliWkpnSVJiYWNNSk1tMDJpaFN1dURudnZ1YzFUOG1EMkYyL0N6S1JlQzh2YUV6MzNCV1E2ZDhiMStmMndlL05GZElhNFJnTStqSjVsNVg0a3ZQdUY1V1pxQ05ucmdLUkZlUmxhekpzdjg1TS0tWlhEa1gwdmlna1FrR1dsbkZ3WjFqQT09--9e4c4c2ce38d9cea7549bb35f4ba2fa5783c5a45
Host: www.jianshu.com
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest
其中除了name是自己添加的键值对外,其它如:name,Cookie,Host 都是HTTP1.1协议支持的首部字段。
-
请求体
请求体里面包含请求的实际数据。对于GET请求,请求体是为空的。对于POST请求,请求体一般不为空,我们实际的业务数据都存放于请求体当中。
以下是对的请求体,请求体为一段json(application/json)数据:{"name":"ios"}
POST /?name=iOS&age=10 HTTP/1.1
name: iOS
Content-Type: application/json; charset=utf-8
Cookie: signin_redirect=http%3A%2F%2Fwww.jianshu.com%2F%3Fname%3DiOS%26age%3D10; _maleskine_session=SGhIVENaem04NWVWSE5UMkVGNWFUTGZSR0hlT2J0dUgyWGJ1bFlMS2h6Smx0UnZ0Mk9tR25zWTBubWJZZmU2UkhUT2RMQ3ZZT0lTQ2U2d3NaVDR3TnBTQ1kwcXgyZHJnNkxsSkI3Q0lFYkxkY0xlbzA1Q1Z2MmRIa1RzNkliQnBFMzJQUmRIeXY3MXI0Wk1zZjd2eGliWkpnSVJiYWNNSk1tMDJpaFN1dURudnZ1YzFUOG1EMkYyL0N6S1JlQzh2YUV6MzNCV1E2ZDhiMStmMndlL05GZElhNFJnTStqSjVsNVg0a3ZQdUY1V1pxQ05ucmdLUkZlUmxhekpzdjg1TS0tWlhEa1gwdmlna1FrR1dsbkZ3WjFqQT09--9e4c4c2ce38d9cea7549bb35f4ba2fa5783c5a45
Host: www.jianshu.com
Connection: close
User-Agent: Paw/3.1.5 (Macintosh; OS X/10.12.6) GCDHTTPRequest
Content-Length: 14
{"name":"ios"}
2、响应报文
响应报文主要分为状态行、响应首部(header)、body(响应体)。header 和 body 空行( CR为回车符,LF换行符 )
的响应抓包:
HTTP/1.1 200 OK
Date: Mon, 16 Oct 2017 02:16:07 GMT
Server: Tengine
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: close
......
-
状态行
状态行主要包含HTTP协议版本、状态码、以及相关原因。
HTTP版本 空格 状态码 空格 原因 CRLF
以下是请求的状态行
HTTP/1.1 200 OK
常见的状态码:
状态码 | 类比 | 说明 |
---|---|---|
1xx | Informational (信息性状态码) | 接收的请求正在处理 |
2xx | Success( 成功状态码) | 请求正常处理完毕 |
3xx | Redirection( 重定向状态码) | 需要进行附加操作以完成请求 |
4xx | Client Error (客户端错误状态码) | 服务器无法处理请求 |
5xx | Server Error 服务器错误状态码 | 服务器处理请求出错 |
-
响应首部
响应首部本质是键值对,是构成HTTP报文的要素之一,它能起到传递额外信息的作用,它的格式如下:
Key: 空格 value CRLF
以下是对的响应首部报文:
HTTP/1.1 200 OK
Date: Mon, 16 Oct 2017 15:18:46 GMT
Server: Tengine
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval' *.jianshu.io api.geetest.com static.geetest.com dn-staticdown.qbox.me zz.bdstatic.com *.google-analytics.com hm.baidu.com push.zhanzhang.baidu.com res.wx.qq.com qzonestyle.gtimg.cn as.alipayobjects.com ;style-src 'self' 'unsafe-inline' *.jianshu.io api.geetest.com static.geetest.com ;
ETag: W/"47a1d42ea1c6321456d016d9de9f7fef"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: signin_redirect=http%3A%2F%2Fwww.jianshu.com%2F; path=/
Set-Cookie: _maleskine_session=MTFVK3ltcVZjNm1vb3dNMmZUUTJJTHVzYWZQaUIvZFNHYnVDWDMzMVdDUVc3dTA3dFpzUGFBUEdPeDRxYk1uQnBTVklOV1RyUFc5bVhhRkxVcS9ySVNEWDgxYTdHQVQ3S2tlaXc0OHNaSWlRa2NrUmRTZC9TZ0tPMGdVOGtIUXhwcnRJWFN0RFgwamFFL1F2S2FoMjQzRmc1ajNYa3RsbERuYnBZQmtKUmtodExaWW5FanRqL2cwRVU1YnN4SUgzN3FFVmdDTzJXK1BJTWN4RW5zZW1wVkxUUGtodTM5bE5zdU9JRDB1aloycUlWNUdieUlnTjVsQkhGSUVzY3Rrai0ta1VEU2xIeDVkK0pDaUdmRXgwWjdWdz09--12010d79a64cb1ee427931e7d7fe04bee742ff52; path=/; HttpOnly
X-Request-Id: 6cbfffbb-d112-45b2-81b5-fbdfa73d9e41
X-Runtime: 0.010188
X-Via: 1.1 wj29:1 (Cdn Cache Server V2.0), 1.1 zhouwtong132:2 (Cdn Cache Server V2.0)
Connection: close
-
响应体
响应体里包含响应的实际数据。响应体的数据类型总称为MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。下面是一些常见的MIME type:
响应内容 |
---|
text/plain |
text/html |
text/css |
image/jpeg |
image/png |
image/svg+xml |
audio/mp4 |
video/mp4 |
application/javascript |
application/pdf |
application/zip |
application/atom+xml |
以下是的响应报文,响应体为 text/html :
HTTP首部字段
HTTP首部字段上面已经提到过,以下是 HTTP1.1 支持的各种字段,主要分为四种:1、通用首部字段;2、请求首部字段;3、响应首部字段;4、实体首部字段。
1、通用首部字段,即请求报文和响应报文都可以使用的字段,以下是通用字段表:
字段名 | 说明 |
---|---|
Cache-Control | 控制缓存行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Warning | 错误通知 |
Via | 代理服务器的相关信息 |
2、请求首部字段,即请求报文可以使用的字段,以下是请求报文字段表:
字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorizabon | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag ) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与If-Match相反 ) |
lf-Range | 资源未更新时发送实体Byte的范围请求 |
If-Unmodified-Since | 比较资源的更新时间( 与If-Modified-Since 相反I |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中URl的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP客户端程序的信息 |
3、响应首部字段,即响应报文可以使用的字段,以下是响应报文字段表:
字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
3、实体首部字段,即针对请求报文和响应报文的实体部分使用的首部,主要是补充了实体资源相关信息,以下是实体首部字段表:
字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
(待续)