重新学习web后端开发-003-了解http请求

274 阅读7分钟

black-and-white-blackboard-business-356043 (1).jpg

语言作为工具,对于我们之重要,正如骏马对骑士的重要,最好的骏马适合于最好的骑士,最好的语言适合于最好的思想。—— 但丁

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 持久连接、管道机制、分块传输编码、
新增了许多动词方法:PUTPATCHHEAD
OPTIONSDELETE 、请求的头信息新增了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请求包括三个部分:

  1. 请求行
  2. 请求头
  3. 消息体(body)[可选]

2.1 请求行

GET /hello HTTP/1.1

包括三个部分:

  1. 请求方法,这里是GET
  2. 访问资源url,这里是/hello
  3. 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响应相关的内容。