语言作为工具,对于我们之重要,正如骏马对骑士的重要,最好的骏马适合于最好的骑士,最好的语言适合于最好的思想。—— 但丁
1. http协议发展
自1991年发布第一个HTTP版本V0.9标准以来,经过了多年的发展,最新的HTTP版本V2已于2015年发布,同时下一代版本HTTP V3也在制定中。然而,当前使用最为广泛的是1.1版本,同时正在往2.0版本过渡,后续文章中将会介绍HTTP/2的情况,相较之前的版本,2.0版本有非常大的变化。
发布时间 | 版本 | 特点 | 相关文档 |
---|---|---|---|
1991 | 0.9 | 该版本极其简单,只有一个命令GET
|
|
1996 | 1.0 | 支持任何格式的内容,协议格式变化。新增功能还包括 状态码(status code)、多字符集支持、 多部分发送(multi-part type)、权限(authorization)、 缓存(cache)、内容编码(content encoding)等。 |
|
1997 | 1.1 | 持久连接、管道机制、分块传输编码、 新增了许多动词方法: PUT 、PATCH 、HEAD 、 OPTIONS 、DELETE 、请求的头信息新增了Host 字段 |
RFC 7230 ~ 7235 |
2015 | 2.0 | 二进制协议、多工、数据流、头信息压缩、服务器推送 | RFC 7540 |
提示:后续如无特殊说明,都以http v1.1为准。
2. http请求
在上篇文章中,我们向"/hello"发起了一个http请求,下面具体分析一下。
GET /hello HTTP/1.1
Host: localhost:9800
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
<上面一行是一个空行CRLF, 同时请忽略本行的说明文字>
其中,第1行是请求行,第2-10行都是请求头,第11行是一个空行,没有body消息。
一个http请求包括三个部分:
- 请求行
- 请求头
- 消息体(body)[可选]
2.1 请求行
GET /hello HTTP/1.1
包括三个部分:
- 请求方法,这里是GET
- 访问资源url,这里是/hello
- http版本,这里是1.1
上面的请求行,简单理解就是:采用http 1.1协议,向/hello发送一个GET请求,希望获取到该url对应的资源。
这里,我们要重点了解下请求方法。有过开发经验,尤其是restful api接口开发经验的朋友,应该比较了解常用的请求方法。比如:GET、POST、PUT、DELETE等。
- 关于restful api接口的规范和实践使用,会在后续文章中具体介绍
2.1.1 请求方法(9种)
- GET - 可以理解为查询行为,获取指定的资源,一般用来获取数据。
- POST - 可以理解为新增行为。服务端会根据请求的内容,在服务器上创建相应的资源。
- PUT - 可以理解为修改行为。服务端会根据请求的内容,如果对应的URI存在,则进行修改。如果不存在,则进行创建。(可选)
- DELETE - 可以理解为删除行为。服务端会删除对应的URI资源。
上述四种方法,是在做后端开发中会经常用到的。我们常说的“CRUD-增删改查”,就可以简单一一对应到相应的方法上。
- HEAD - 该方法和GET类似,只是服务器仅返回http状态行和头部信息,不会返回body内容。可以用于只需要获取相应资源meta信息,而不需要获取整个资源内容。
Tip:该方法可在实践中用于“服务探活”或者用于心跳机制中的”心跳包“。
- OPTIONS - 该方法可以返回针对特定URI所支持的http方法。常用于检查web服务针对特定资源所提供的功能。后续我们还会提到它,用于解决前端跨域问题。
- CONNECT - 该方法用于将请求转换为透明的tcp/ip隧道。常用于HTTPS。
- PATCH - 该方法可用于更新特定资源的部分内容。相对很少使用。
- TRACE - 该方法使服务器原样返回任意客户端请求的任何内容。主要用于协议调试。存在安全问题,建议服务端关闭,不要使用。
2.1.1.1 方法特性 - 安全性
某些方法在设计时就被定义为"安全方法"。所谓的安全方法是指用于检索数据,不会改变服务资源的状态。专业点的说法就是不会产生”副作用“(side effects)。比如:get方法不会改变资源的内容,是安全的,而delete方法会删除特定的资源,是不安全的。
2.1.1.2 方法特性 - 幂等性
某些方法在设计时就被定义为幂等的。所谓幂等是指相同的请求,无论调用多少次,都会产生一样的作用。比如:DELETE。对于任一个DELETE请求,无论执行多少次,其产生的作用是一样的。也就是说删除某个特定资源一次,和删除多次,其对资源的作用是一样的。
Tip:要注意区分安全性和幂等性的区别。安全性是强调不会产生副作用,而幂等性强调的是多次请求所产生的作用是一样的。
2.1.1.3 方法小结
来自维基百科的表格,略作调整
方法名 | RFC文档 | Request has Body | Response has Body | 安全 | 幂等 | 可缓存 |
---|---|---|---|---|---|---|
GET | RFC 7231 | Optional | Yes | Yes | Yes | Yes |
POST | RFC 7231 | Yes | Yes | No | No | Yes |
PUT | RFC 7231 | Yes | Yes | No | Yes | No |
DELETE | RFC 7231 | No | Yes | No | Yes | No |
HEAD | RFC 7231 | No | No | Yes | Yes | Yes |
OPTIONS | RFC 7231 | Optional | Yes | Yes | Yes | No |
CONNECT | RFC 7231 | Yes | Yes | No | No | No |
PATCH | RFC 5789 | Yes | Yes | No | No | No |
TRACE | RFC 7231 | No | Yes | Yes | Yes | No |
注意:POST方法不是幂等的。在接口开发时,要处理可能会出现的幂等问题。关于接口幂等问题的处理,可以参考后续的文章。PUT和DELETE方法是幂等的,GET也是。
2.1.2 访问资源
/hello,为该GET请求的资源地址。和头部区域中的HOST部分一起确定唯一的资源地址。
2.1.3 协议版本号
HTTP/1.1 - 表明使用的http协议版本是1.1
2.2 请求头
请求头位于请求行之后,使用key-value的格式,并以CRLF结尾。也就是说每行都是一个键值对。请求头可以包括多个键值对。最后使用一个空行,来表明整个请求头的结束。
标准请求头字段有36个,非标准的有十多个。作为后端开发人员,需要了解一些常见的请求头。我们首先介绍下'hello,world'中的请求头,后续出现其它的请求头字段时再一一说明。
注意:请求头字段名是大小写不敏感的,而方法名都是大写的,是大小写敏感的。
2.2.1 "hello, world" 请求头
字段 | 描述 | 例子 | 备注 |
---|---|---|---|
Host | 主机地址,包括域名和端口号。(用于支持虚拟主机) | Host: localhost:9800 | HTTP/1.1是强制必须要有的。HTTP/2 将不使用该字段。 |
Connection | 当前连接控制选项 | Connection: keep-alive | HTTP/1.1默认是keep-alive。HTTP/2 将不使用该字段。 |
User-Agent | http客户端名称 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 |
服务端可根据此字段了解客户端的类型。常用于访问统计。 |
Accept | 可接受的响应内容媒体格式 | text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,/;q=0.8 |
|
Accept-Language | 可接受的语言 | Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7 | |
Accept-Encoding | 可接受的数据压缩编码格式 | Accept-Encoding: gzip, deflate, br | 可用于提升数据传输性能 |
Pragma | 特殊指令,常用于进行缓存控制 | Pragma: no-cache | 支持HTTP/1.0,HTTP/1.1 |
Cache-Control | 缓存控制指令 | Cache-Control: no-cache | 支持HTTP/1.1 |
Upgrade-Insecure-Requests | 告诉服务端,建议从http升级到https。常用于过度阶段。 | Upgrade-Insecure-Requests: 1 | 非标准字段 |
Tip:
- 关于Connection的keep-alive,详见后续文章。
2.3 消息体-body部分
该GET请求中,消息体部分为空。后续出现具有body部分的请求时,我们会具体分析。
3. 小结
本节我们主要介绍了http协议请求部分的基本内容。当然这只是http协议的一部分,也是作为web后端开发人员需要掌握的基本知识。在后面的文章中,会逐渐展开http协议的相关内容。希望通过具体项目开发实践和所使用的技术背后的知识相结合,能够给大家带来帮助。下一节,我们将分析http响应相关的内容。