87570495 2019-06-26
HTTP是前后端交互很重要的一个部分,然而许多前端工程师对此并不了解,也不知道如何学习。这篇文章就是HTTP小白入门,看完后一定能对HTTP的知识有进一步的认识。
当我们在浏览器的地址栏里输入URL时,请求会被发往服务器,服务器收到请求后会把资源文件发送给客户端。
而这个通信过程使用一种名叫HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成客户端到服务端的一系列运作流程。
我们通常使用的网络是在TCP/IP协议族上运作的,HTTP属于它的一个子集。
其中最重要的一点就是TCP/IP协议族的分层。它分为以下四层:应用层、传输层、网络层、数据链路层。
发送端在层与层之间传输数据时,每经过一层时必定会打上一个该层对应的首部信息。而接收端在层与层之间传输数据时,每经过一层则把对应的首部消除。
URI(Uniform Resource Identifier,统一资源标识符)
URL(Uniform Resource Locator,统一资源定位符)
URI用字符串标识某一互联网资源,就像人的身份证号一样,一个人只有一个身份证号,一个资源也只有一个标识符。
URL表示资源的地点(在互联网上所处的位置)。
由此可见URL是URI的子集。
在通过HTTP协议通信与客户端和服务端之间的时候,客户端会发送请求报文,而服务端会发送响应报文。
请求报文的一个例子:
GET index.html HTTP/1.1 Host: www.baidu.com Content-Type: application/x-www-form-urlencoded Connection: keep-alive ... name=Peggy&age=24
请求报文是由请求方法、请求URI、协议版本、可选的请求首部字段和内容实体组成。
响应报文的一个例子:
HTTP/1.1 200 OK date: Mon, 5 Mar 2018 11:21:20 GMT Content-Type: text/html ... <html> ...
请求报文是由协议版本、状态码、解释状态码的原因短语,可选的响应首部字段和内容实体组成。
即HTTP协议自身不对请求和响应之间的通信状态做保存。
例如客户端向同一个服务端发送请求,服务端并不知道上一次给客户端发送的是什么内容,客户端也不知道服务端上一次给自己发送的是什么内容。
HTTP/1.1中可使用的方法:
GET 获取资源
POST 传输实体主体
HEAD 获得报文首部
OPTIONS 询问支持的方法
基本不会用到的方法:
PUT 传输文件
DELETE 删除文件
TREACE 追踪路径
CONNECT 要求用隧道协议连接代理
在HTTP的初始版本中,每进行一次HTTP连接就要断开一次TCP连接。
当资源量变多以后,这种方式变得非常耗性能。
在HTTP/1.1和部分HTTP/1.0里实现了持久连接(HTTP keep-alive)。
(在HTTP/1.1中,所有连接默认都是持久连接)
持久连接即只要任意一段没有提出明确的断开连接的要求前TCP连接始终保持。
持久连接同时使得管线化发送请求的方式得以实现。
管线化是指客户端可以发送多次请求到服务端,而不需要等待上一次请求得到响应的时候才能进行下一次请求,实现并行发送请求。
因为HTTP是无状态的协议,而很多业务需求让我们必须记录用户的状态,cookie就是为解决这个问题而产生的。
客户端第一次发送的请求并不含有cookie,当服务端在接收到请求后在响应报文里会加入一个set-Cookie的首部字段;而客户端第二次发送请求时会自动在请求报文的首部里加入cookie,这样收到请求的服务端就知道发送请求的是谁了。
HTTP报文可分为报文首部和报文主体两部分。(报文主体不是必须的)
两者由CR+LF划分。(CR-Carriage Return,回车符, 16进制 0x0d;LF-Line Feed,换行符, 16进制 0x0a)
请求报文首部包含请求行和其他首部字段,响应报文首部包含状态行和其他首部字段。
HTTP协议的内容编码可以把实体压缩变小之后再发送。
常用的内容编码方式有:
在传输大容量数据时,通过把数据分割成多块,可以让浏览器逐步显示页面。这个功能就叫做分块传输编码(Chunked Transfer Coding)。
当发送多个不同类型的数据时,例如文本、图片、视频,需要使用一种名叫多部分对象集合(Multipart)的方法来容纳不同类型的数据。通常在图片或文件上传时会用到。
对部分对象集合包含的对象如下:
有这样一种情况,当下载文件到一半的时候失败了,重新下载需要从失败的地方开始。所以就需要指定范围下载,而指定范围发送的请求叫做范围请求(Range Request)。
在执行范围请求时,需要用到首部字段Range来指定资源的byte范围。例如:
Range: byte=-3000, 5000-7000
指的是请求从一开始到3000字节,以及5000到7000字节。
针对范围请求,响应会返回状态码206 P爱人天了Content和响应报文。
如果服务端无法响应返回请求,会返回状态码200 OK和完整的实体内容。
同一个网站可能有中文或英文版本,根据浏览器的默认语言显示相应的页面,这样的机制成为内容协商(Content Negotiation)。
内容协商机制是指客户端和服务端就响应的资源内容进行交涉,然后提供给客户端最为合适的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的基准。
以下是作为判断基准的首部字段:
状态码用来告知请求结果的状态。状态码以3位数字和原因短语组成。
数字中的第一位指定了响应的类别:
200 OK (表示请求被正常处理了)
204 Not Content (表示请求成功,但返回的响应报文不含实体的主体部分)
206 Partial Content (表示客户端的范围请求成功执行)
301 Moved Permanently(永久重定向,表示请求的资源已经分配了新的URI)
302 Found(临时重定向,表示请求的资源已经分配了新的URI,希望用户本次能使用新的URI访问)
303 See Other(表示请求的资源有另一个URI,希望用户以GET方法定向请求资源)
304 Not Modified(表示文档的内容(自上次访问以来或者根据请求的条件)并没有改变)[不包含任何响应的主体部分]
400 Bad Request(表示请求报文中存在语法错误)
401 Unauthorized(表示发送的请求需要有通过HTTP认证的认证信息)
403 Forbidden(表示请求资源的访问被服务器拒绝了)
404 Not Found(表示无法在服务器找到请求的资源)
501 Internal Server Error(服务器在执行请求时发生了错误)
503 Service Unavailable(表示服务器暂时处于超负载或者正在进行停机维护)
这里只对常用的状态码做简单介绍,具体的详细学习可以自行百度或看其他文章。
首部字段有很多,在这里不一一说明,可点此查看。具体学习请自行百度。
写过小程序的应该知道,微信的request不封装基本上不能用,写的显的太冗长,而且是回调式的,回调地狱什么的就不说了,可读性差。下面是我的封装代码,顺便支持一下promise。加了登录锁后的代码如下: