HTTP——需要知道的协议

本文属于原创文章,转载请注明–桃源小盼

笔者语

作为一个程序员,当我们访问一个接口,服务器接收到并返回结果,那么中间的流程是怎么处理的呢?这个请求是如何到达服务器,服务器又是怎样返回内容的?

如果没有HTTP协议,接口请求具体实现的细节, 都需要每个客户端和服务器各自约定和实现,而自己的规则,又不能适用于别人。这给开发带来了极大的不便,HTTP就是为此而设计的。HTTP协议用来约定双方的行为规范,让相关开发者按照相同的规则来开发网站和工具。

HTTP协议就像发快递时填写的发货单,规定必须填写收货人,地址和手机号码,只有这样才能准确送给收货人。HTTP则是规定了如何在两台电脑间发送和接收超文本。

起源历史

1980年,蒂姆·伯纳斯·李在CERN(欧洲核子研究组织)时,为了方便各地研究人员共享信息,提出了一个设想,”借助于超文本,连接成可互相浏览的WWW(万维网)项目”。

到了1989年,伯纳斯·李看到了将超本文与互联网结合的机会,那时已经有了在电脑上显示信息的超文本系统,也有了域名系统和TCP/IP网络传输协议。伯纳斯·李又为此设计制作世界上第一个网页浏览器和网页服务器,将这一切组合起来,就能实现浏览处于世界任何地方服务器上的超文本信息。在这个过程中,由于TCP/IP协议族中没有适合传输超文本的协议,李博士又发起了HTTP(超文本传输协议)的提议。

于是在1989年,HTTP协议诞生了。现如今最广泛使用的协议版本是在1999年制定的HTTP 1.1。

`蒂姆·伯纳斯·李在2017年4月5日,获得了2016年度图灵奖,被誉为万维网之父。他发明了浏览器,
HTTP,HTML,URI等一系列相关的万维网技术。`

TCP/IP协议族

现实世界中的各行各业都有自己的行业规则,违反规则,步履艰难,而尊重规则,便如鱼得水。网络世界也需要各种各样的规则,TCP/IP协议族就是这些规则的总称。而HTTP协议是其中的一种,负责传输超文本(HyperText)。

TCP/IP协议族一共分为四层,包含不同的协议。应用层、传输层、网络层和链路层。

这张图简单描述了,打开一个网站背后都发生了什么?

《HTTP——需要知道的协议》

  1. 通过DNS协议,获得访问域名对应的服务器IP地址。DNS协议属于应用层。

  2. 紧接着用到了HTTP协议,将生成的HTTP报文发送给服务器。HTTP协议属于应用层。

  3. 数据在网络中的传输是十分重要的,为了保证数据传输的稳定性和完整性,制定了TCP协议,它将数据分割成报文段,按序号传输。TCP协议属于传输层。

  4. 客户端发起的请求,怎么在众多机器中找到对应那一台,需要IP协议来寻找一条路径。IP协议属于网络层。

  5. 最后服务器收到了请求,把响应内容按照之前的步骤,返回给客户端。

HTTP协议概述

客户端发出请求报文,服务器收到请求,经过处理,把响应报文返回客户端,连接断开,一次请求结束。HTTP协议是无状态协议。

在1990年W3C发布了第一个HTTP/0.9版本,这个版本只支持GET请求。

1996年发布了HTTP/1.0版本,这是第一个广泛使用的版本,支持了多媒体类型和各种HTTP首部字段。

但真正应用至今的是在1999年发布的HTTP/1.1版本,它修复了一些结构的缺陷,并引入了性能优化的措施。本文以下的内容都以HTTP/1.1为基础展开。

我们用chrome浏览器打开http://www.w3c.org这个网站。打开开发者工具的network项,看看第一个请求的详细信息。

《HTTP——需要知道的协议》

请求报文由请求地址、请求方法、协议版本、首部字段和内容实体。

GET /index.html HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)
Host: w3c.org

响应报文由状态码及解释短语、协议版本、首部字段和响应实体。

HTTP/1.1 200 OK 
Content-Type: text/html
Content-Length: 137582
Server: Apache 0.84

<html>
  <body>Hello World</body>
</html>

HTTP请求方法

HTTP/1.1 支持多种请求方法,最常用的还是get和post方法。

HTTP通信是建立在TCP连接的基础上,早期版本每次通信都需要重新连接、断开TCP。所以在HTTP/1.1下,实现了在一次TCP连接中进行多次HTTP通信的能力,大大提高了服务器的响应速度。同时也支持并行发送请求,一般浏览器是支持同时6个连接。

GET

gee方法是安全的请求方法,获取已经存在的资源或者是查询一些数据,通常会把请求参数拼接在url中。

HEAD

head方法也是安全的,但它与get的不同在于,它不会返回响应实体内容,只返回响应首部。一般会用来确认请求url的有效性。

POST

post方法会把请求内容放在请求实体中,而不是拼接在url中。所以一般查询信息用GET方法,提交表单数据使用post方法。

OPTIONS

查询指定url资源支持的请求方法,例如支持get和head。

TRACE

一般请求发出后,会经过多层代理服务器,这个方法就是用来确认请求发出后发生的一系列操作。但会引起跨站追踪攻击,一般不用。

PUT与DELETE

put是用来往服务器上传文件,而delete就是删除服务器上的文件。但是这两个方法没有验证机制,会产生不安全问题,一般服务器都不做支持。

状态码

状态码用来表示服务器返回的请求结果。由三位数字加解释短语组成,例如 200 ok。
虽然状态码有很多,但是也可分门别类,并不需要掌握所有,也对返回的结果有个大致的了解。

状态码响应类别原因短语
1xx信息性状态码(Informational)服务器正在处理请求
2xx成功状态码(Success)请求已正常处理完毕
3xx重定向状态码(Redirection)需要进行额外操作以完成请求
4xx客户端错误状态码(Client Error)客户端原因导致服务器无法处理请求
5xx服务器错误状态码(Server Error)服务器原因导致处理请求出错

当我们知道了,首位数字是定义状态码的类型后,理解更多的状态码也就简单起来。
下面,再详细介绍一些常见的状态码。

200 OK

这个是最常见的,表示请求在服务器被正确处理了。

204 No Content

请求在服务器端被正确处理了,但是返回的响应报文中没有实体内容。一般用在只是客户端向服务器发送信息,而服务器不用向客户端返回什么信息的情况。

301 Moved Permanently

永久性重定向,代表资源的链接已经更换了url,在响应报文中会包含新的链接地址。

304 Not Modified

当发出的请求中有附加条件(首部字段有if-*)时,服务器允许访问,但是不满足条件的情况。

400 Bad Request

请求报文内容存在语法错误,服务器处理不了。

401 Unauthorized

发送的请求中含有HTTP认证信息,认证未通过。
返回401的响应必须包含一个适用于被请求资源的WWW-Authenticate首部以质询用户信息

403 Forbidden

请求的资源拒绝被访问,一般是无权限访问。

404 Not Found

这个也很常见,请求的资源服务器找不到。

500 Internal Server Error

服务器在处理请求时,出错了。一般是服务器发生了异常状况。

HTTP首部

首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。通俗点讲,浏览器和服务器会根据这些字段做出不同的反应,每个字段相当于一条配置信息。
首部字段类似于键值对,请求报文和响应报文都包含首部信息。

这是一段请求首部字段,例如Accept表示浏览器可以接受的响应报文实体类型。

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Host:www.w3.org
If-Modified-Since:Thu, 04 May 2017 23:40:12 GMT
If-None-Match:"a384-54ebb4b41af00;89-3f26bd17a2f00-gzip"

首部字段分为了五种类型,通用首部、请求首部、响应首部、实体首部和拓展首部。

类型说明
通用首部是请求和响应都会用到的字段
请求首部是客户端向服务器发送请求时,报文中包含的首部字段
响应首部是服务器向浏览器返回响应报文时,包含的首部字段
实体首部是请求报文和响应报文中针对实体内容的首部字段
拓展首部是非标准首部字段,由开发者根据自身需求自由定义和实现

以下列表,提供一些首部的简单说明,每个字段的具体使用都不一样,实际应用还是查看详细介绍。

通用首部

字段名说明
Cache-Control控制缓存行为
PragmaHTTP/1.0遗留字段,也是用于控制缓存机制
Transfer-Encoding传输报文主体的编码方式
Trailer报文主体之后的首部字段,用于分块传输
Upgrade检测HTTP协议是否可用更高版本
Connection控制不再转发给代理的字段、连接的管理
Date创建报文的日期
Via追踪客户端与服务器之间报文的传输路径,通常指代理服务器
Warning缓存相关警告

请求首部

字段名说明
Accept客户端可接受的媒体类型及相关优先级,q值表示权重
Accept-Charset客户端可接受的字符集及优先顺序
Accept-Encoding客户端支持的内容编码及优先顺序
Accept-Language客户端可处理的自然语言集,以及优先级
Authorization客户端的认证信息,一般是证书信息
Host请求资源所在服务器的主机名和端口号
If-Match比较实体标记
If-Modified-Since比较资源更新时间
If-None-Match比较实体标记(与If-Match作用相反)
If-Range资源未更新时发送实体Byte的范围请求
If-Unmodified-Since比较资源更新时间(与If-Modified-Since作用相反)
Max-Forwards最大传输逐跳数(TRACE或OPTIONS方法会用到)
Range范围请求的实体字节段
Referer请求页面的原始url
TE传输编码及优先级
User-Agent请求客户端的自身信息

响应首部

字段名说明
Accept-Ranges服务器是否接受字节范围请求
Age服务器响应创建经过的时间
ETag资源配置信息
Location服务器告知客户端重定向url
Proxy-Authorization代理服务器向客户端发起的认证信息
Retry-After服务器告知客户端再次请求的时间
Server服务器应用名、版本号等相关信息
Vary代理服务器的缓存管理信息
WWW-Authorization服务器对客户端的认证信息

实体首部

字段名说明
Allow资源支持的请求方法
Content-Encoding实体内容的编码方式
Content-Language实体内容的自然语言集
Content-Length实体内容字节长度
Content-Location实体内容替代url
Content-MD5实体内容的报文摘要
Content-Range实体内容的位置范围
Content-Type实体内容对应的媒体类型
Expires实体内容失效日期
Last-Modified实体内容最后修改日期

Cookie

HTTP协议是无状态的,如果我们今天登录了一个网站,明天重新打开网站时,能自动登录,怎么办?
那就得靠cookie来解决了。它能在客户端保存用户的基本信息,当我们下次访问该网站,浏览器会把cookie一起发送给服务器,服务器就会根据这些信息来判断你是否登陆过。

cookie是网景公司的前雇员卢·蒙特利在1993年3月的发明的。cookie数据也是键值对的形式,它和网站以及网页是关联在一起的。如果保存cookie值指定了网站地址,访问其他网站时并不会发送这些cookie值。

访问一个网站,打开chrome的开发者工具,application中可以看见cookie的信息。

《HTTP——需要知道的协议》

cookie相关的首部字段

  • Expires:是用来设置cookie的绝对过期时间,默认cookie的生存周期是跟随页面的,页面关闭即失效。

  • Max-Age:是用来设置cookie的相对过期时间,如果同时设置了Expires值,以Max-Age为准。

  • path: 是用来指定与cookie绑定的网页地址,默认情况下,和该网页同一目录下的网页也能访问该cookie。

  • domain: 指定与该cookie绑定的域名,该域名下的网页都可以访问该cookie。

  • secure: 标明传输cookie值的方式。默认情况下,cookie是在不安全的HTTP链接传输,如果设定了该值,cookie将必须处于更安全的方式下才可以传输,比如接下来介绍的HTTPS。

cookie的缺陷

  • 传输:cookie在每一次的HTTP请求中都被附加发送,增加了传输流量。

  • 安全:cookie是明文传输,有安全性问题,会被劫持和篡改。

  • 大小:cookie有大小限制是4kb,更复杂的数据存储是无法满足的。

HTTPS

HTTP协议传输的数据是明文未加密的,为了安全性,网景公司设计了SSL协议(安全套接层),用SSL建立一个安全的通信线路后,就可以在这条线路上进行普通的HTTP通信了,与SSL组合起来就是 HTTPS了,不过现在使用更多的是TLS(安全层传输协议)。

网站使用HTTPS需要申请一个证书,由第三方的可信赖机构提供的,这是为了防止身份伪装。

HTTPS的握手过程

《HTTP——需要知道的协议》

  1. 客户端发送协议版本,随机码,支持的加密算法和压缩方法

  2. 服务器确认使用的协议版本和加密算法,生成随机码,发送服务器证书

  3. 客户端验证服务器证书,生成48字节key,使用服务器公钥加密key,发送加密信息,客户端握手结束

  4. 服务器将两个随机码+key组合生成本次通信密钥,用来加密信息,服务器握手结束

接下来的通信都将在此加密通信下进行,以上任何确认过程失败,都将断开加密通信。

插曲OpenSSL

看过锤子发布会的,都知道这个组织,但具体干什么的恐怕也没几个人清楚。它是HTTPS中SSL和TLS的具体实现库。
OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,其主要库是以C语言所写成,实现了基本的加密功能,实现了SSL与TLS协议。OpenSSL可以运行在绝大多数类Unix操作系统上,OpenVMS与 Microsoft Windows。

未来的HTTP/2

随着互联网的发展,web页面的数据量暴增,服务多年的HTTP/1.1已经显露疲态,由于协议是固定的,所以浏览器,服务器和开发者等都通过各自的手段,来加强服务的响应能力,减缓HTTP/1.1的不足之处。

谷歌开发了SPDY这个实验性协议来提升http的性能,HTTP/2的草案就是基于SPDY3.0展开的。HTTP/2的主要目标是改进传输性能,实现低延迟和高吞吐量。升级HTTP2不会影响原有的网站应用。

二进制分帧

HTTP/2将所有传输的信息分割为更小的消息和帧,并对它们采用二进制格式的编码。之前版本的数据传输都是纯文本的方式,二进制的解析更高效,更准确。这是整个HTTP/2性能提升的基础。

多路复用的流

当前问题: HTTP/1.1协议中,一个tcp连接处理一个HTTP请求。例如同时有A和B两个请求,先发送A请求,A请求响应结束,再发送B请求,如果A请求处理的时间很长,B也只能等待,这样就造成了线头堵塞。目前每个浏览器可以同时发起6-8个tcp连接,也依然不能很好地解决大量请求的处理。就算开启了管道机制,一个tcp连接同时发送A和B请求,B还是会等在A之后响应。

HTTP/2的方式: HTTP/2中的请求都在一个tcp连接中处理,每个请求和响应都被分解为独立的帧,然后并行交错发送,再在另一端重新组装。请求之间不再互相干扰,从而消除了不必要的等待和延迟,巨大地提升了性能。

头部压缩

由于HTTP是无状态的,所以每一次请求和响应都会携带头信息,而其中很多头信息是相同的,毫无疑问增加了传输的数据量。

所以HTTP/2设计了专门用于压缩头信息的HPACK算法,在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键值对,并进行更新替换。

服务器推送

当我们访问一个网页时,服务器先返回HTML文档,浏览器再根据这个文档,去请求其中包含的图片,样式表和脚本。

而HTTP/2中,服务器可以对一个客户端发送多个响应,而无需客户端再多起多次请求,客户端可以控制该功能的开启。

参考

  1. http超文本传输协议——维基百科

  2. 蒂姆·伯纳斯·李——万维网之父

  3. 超文本——百度百科

  4. HTTP 协议入门——阮一峰

  5. 99%的人理解错 HTTP 中 GET 与 POST 的区别

  6. 一次完整的HTTP请求与响应涉及了哪些知识?

  7. 《图解HTTP》

  8. 《HTTP权威指南》

    原文作者:HTTP
    原文地址: https://segmentfault.com/a/1190000009537864
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞