HTTP 协议是基于 TCP 协议出现的,对 TCP 协议来说,TCP 协议是一条双向的通讯通道,HTTP 在 TCP 的基础上,规定了 Request-Response 的模式。这个模式决定了通讯必定是由浏览器端首先发起的。
大部分情况下,浏览器的实现者只需要用一个 TCP 库,甚至一个现成的 HTTP 库就可以搞定浏览器的网络通讯部分。HTTP 是纯粹的文本协议,它是规定了使用 TCP 协议来传输文本格式的一个应用层协议。
HTTP 协议格式
HTTP Method(方法)
- GET 浏览器通过地址栏访问页面都是 GET 方法。
- POST 表单提交产生 POST 方法。
- HEAD HEAD 则是跟 GET 类似,只返回请求头,多数由 JavaScript 发起。
- PUT PUT 表示添加资源,这只是语义上的一种约定,并没有强约束。
- DELETE DELETE 表示删除资源,这只是语义上的一种约定,并没有强约束。
- CONNECT CONNECT 现在多用于 HTTPS 和 WebSocket。
- OPTIONS OPTIONS 一般用于调试,多数线上服务都不支持。
- TRACE TRACE 一般用于调试,多数线上服务都不支持。
HTTP Status code(状态码)和 Status text(状态文本)
- 1xx:临时回应,表示客户端请继续。
- 2xx:请求成功。
-
200:请求成功。
-
201 :当服务器依照客户端的请求创建了一个新资源时,发送此响应代码。
-
202:客户端的请求无法或将不被实时处理。请求稍后会被处理。
-
**204:若服务器拒绝对PUT、POST或者DELETE请求返回任何状态信息或表示,那么通常采用此响应代码。**服务器也可以对GET请求返回此响应代码,这表明“客户端请求的资源存在,但其表示是空的”。注意与304("Not Modified")的区别。204常常用在Ajax应用里。服务器通过这个响应代码告诉客户端:客户端的输入已被接受,但客户端不应该改变任何UI元素。
-
206:它跟200类似,但它用于对部分GET请求(即使用Range请求报头的GET请求)的响应。部分GET请求常用于大型二进制文件的断点续传。
-
- 3xx: 表示请求的目标有变化,希望客户端进一步处理。
- 301&302:永久性与临时性跳转。
- 303:请求已经被处理,但服务器不是直接返回一个响应文档,而是返回一个响应文档的URI。该响应文档可能是一个静态的状态信息,也可能是一个更有趣的资源。
- **304:跟客户端缓存没有更新。**与204类似,响应实体主体都必须为空。但204用于没有主体数据的情况,而304用于有主体数据,但客户端已拥有该数据,没必要重复发送的情况。这个响应代码可用于条件HTTP请求(conditional HTTP request).如果客户端在发送GET请求时附上了一个值为Sunday的If-Modified-Since报头,而客户端所请求的表示在服务器端自星期日(Sunday)以来一直没有改变过,那么服务器可以返回一个304响应。服务器也可以返回一个200响应,但由于客户端已拥有该表示,因此重复发送该表示只会白白浪费宽带。
- 307:请求还没有被处理,因为所请求的资源不在本地。它在另一个URI处。客户端应该向那个URI重新发送请求。就GET请求来说,它只是请求得到一个表示,该响应代码跟303没有区别。当服务器希望把客户端重新定向到一个镜像站点时,可以用307来响应GET请求。但对于POST,PUT及DELETE请求,它们希望服务器执行一些操作,307和303有显著区别。对POST,PUT或者DELETE请求响应303表明:操作已经成功执行,但响应实体将不随本响应一起返回,若客户端想要获取响应实体主体,它需要向另一个URI发送GET请求。而307表明:服务器尚未执行操作,客户端需要向Location报头里的那个URI重新提交整个请求。
- 4xx:客户端请求错误。
-
**400:这是一个通用的客户端错误状态。**当其他4XX响应代码不适用时,就采用400。此响应代码通常用于“服务器收到客户端通过PUT或者POST请求提交的表示,表示的格式正确,但服务器不懂它什么意思”的情况。
-
**401:客户端试图对一个受保护的资源进行操作,却又没有提供正确的认证证书。**客户端提供了错误的证书,或者根本没有提供证书。这里的证书(credential)可以是一个用户名/密码,也可以市一个API key,或者一个认证令牌。客户端常常通过向一个URI发送请求,并查看收到401响应,以获知应该发送哪种证书,以及证书的格式。如果服务器不想让未授权的用户获知某个资源的存在,那么它可以谎报一个404而不是401。这样做的缺点是:客户端需要事先知道服务器接受哪种认证--这将导致HTTP摘要认证无法工作。
-
**403:无权限。**客户端请求的结构正确,但是服务器不想处理它。这跟证书不正确的情况不同--若证书不正确,应该发送响应代码401。该响应代码常用于一个资源只允许在特定时间段内访问,
或者允许特定IP地址的用户访问的情况。403暗示了所请求的资源确实存在。跟401一样,若服务器不想透露此信息,它可以谎报一个404。既然客户端请求的结构正确,那为什么还要把本响应代码放在4XX系列(客户端错误),而不是5XX系列(服务端错误)呢?因为服务器不是根据请求的结构,而是根据请求的其他方面(比如说发出请求的时间)作出的决定的。 -
**404:表示请求的页面不存在。**这也许是最广为人知的HTTP响应代码了。404表明服务器无法把客户端请求的URI转换为一个资源。相比之下,410更有用一些。web服务可以通过404响应告诉客户端所请求的URI是空的,然后客户端就可以通过向该URI发送PUT请求来创建一个新资源了。但是404也有可能是用来掩饰403或者401.
-
**405:客户端试图使用一个本资源不支持的HTTP方法。**例如:一个资源只支持GET方法,但是客户端使用PUT方法访问。
-
**406:当客户端对表示有太多要求,以至于服务器无法提供满足要求的表示,服务器可以发送这个响应代码。**例如:客户端通过Accept头指定媒体类型为application/json+hic,但是服务器只支持application/json。服务器的另一个选择是:忽略客户端挑剔的要求,返回首选表示,并把响应代码设为200。
-
**409:你请求的操作会导致服务器的资源处于一种不可能或不一致的状态。**例如你试图修改某个用户的用户名,而修改后的用户名与其他存在的用户名冲突了。
-
**410:这个响应代码跟404类似,但它提供的有用信息更多一些。**这个响应代码用于服务器知道被请求的URI过去曾指向一个资源,但该资源现在不存在了的情况。服务器不知道该资源的新URI,服务器要是知道该URI的话,它就发送响应代码301.410和310一样,都有暗示客户端不应该再请求该URI的意思,不同之处在于:410只是指出该资源不存在,但没有给出该资源的新URI。RFC2616建议“为短期的推广服务,以及属于个人但不继续在服务端运行的资源”采用410.
-
411:若HTTP请求包含表示,它应该把Content-Length请求报头的值设为该表示的长度(以字节为单位)。
-
**412:客户端在请求报头里指定一些前提条件,并要求服务器只有在满足一定条件的情况下才能处理本请求。**若服务器不满足这些条件,就返回此响应代码。If-Unmodified-Since是一个常见的前提条件。客户端可以通过PUT请求来修改一个资源,但它要求,仅在自客户端最后一次获取该资源后该资源未被别人修改过才能执行修改操作。若没有这一前提条件,客户端可能会无意识地覆盖别人做的修改,或者导致409的产生。
-
**413:这个响应代码跟411类似,服务器可以用它来中断客户端的请求并关闭连接,而不需要等待请求完成。**411用于客户端未指定长度的情况,而413用于客户端发送的表示太大,以至于服务器无法处理。客户端可以先做一个LBYL(look-before-you-leap)请求,以免请求被413中断。若LBYL请求获得响应代码为100,客户端再提交完整的表示。
-
**414:HTTP标准并没有对URI长度作出官方限制,但大部分现有的web服务器都对URI长度有一个上限,而web服务可能也一样。**导致URI超长的最常见的原因是:表示数据明明是该放在实体主体里的,但客户端却把它放在了URI里。深度嵌套的数据结构也有可能引起URI过长。
-
**415:当客户端在发送表示时采用了一种服务器无法理解的媒体类型,服务器发送此响应代码。**比如说,服务器期望的是XML格式,而客户端发送的确实JSON格式。
如果客户端采用的媒体类型正确,但格式有问题,这时最好返回更通用的400。 -
**416:当客户端所请求的字节范围超出表示的实际大小时,服务器发送此响应代码。**例如:你请求一个表示的1-100字节,但该表示总共只用99字节大小。
-
**417:此响应代码跟100正好相反。**当你用LBYL请求来考察服务器是否会接受你的表示时,如果服务器确认会接受你的表示,那么你将获得响应代码100,否则你将获得417。
-
418:It’s a teapot. 这是一个彩蛋,来自 ietf 的一个愚人节玩笑。(超文本咖啡壶控制协议)
-
- 5xx:服务端请求错误。
- **500:服务端错误。**这是一个通用的服务器错误响应。对于大多数web框架,如果在执行请求处理代码时遇到了异常,它们就发送此响应代码。
- 501:客户端试图使用一个服务器不支持的HTTP特性。
- **502:只有HTTP代理会发送这个响应代码。**它表明代理方面出现问题,或者代理与上行服务器之间出现问题,而不是上行服务器本身有问题。若代理根本无法访问上行服务器,响应代码将是504。
- **503:服务端暂时性错误,可以一会再试。**此响应代码表明HTTP服务器正常,只是下层web服务服务不能正常工作。最可能的原因是资源不足:服务器突然收到太多请求,以至于无法全部处理。由于此问题多半由客户端反复发送请求造成,因此HTTP服务器可以选择拒绝接受客户端请求而不是接受它,并发送503响应代码。
- **504:跟502类似,只有HTTP代理会发送此响应代码。**此响应代码表明代理无法连接上行服务器。
HTTP Head (HTTP 头)
HTTP 头可以看作一个键值对。原则上,HTTP 头也是一种数据,我们可以自由定义 HTTP 头和值。不过在 HTTP 规范中,规定了一些特殊的 HTTP 头。
HTTP Request Body
HTTP 请求的 body 主要用于提交表单场景。实际上,http 请求的 body 是比较自由的,只要浏览器端发送的 body 服务端认可就可以了。一些常见的 body 格式是
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
- text/xml
我们使用 html 的 form 标签提交产生的 html 请求,默认会产生 application/x-www-form-urlencoded 的数据格式,当有文件上传时,则会使用 multipart/form-data
HTTPS
在 HTTP 协议的基础上,HTTPS 和 HTTP2 规定了更复杂的内容,但是它基本保持了 HTTP 的设计思想,即:使用上的 Request-Response 模式。
我们首先来了解下 HTTPS。HTTPS 有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。
HTTP 2
HTTP 2.0 最大的改进有两点,一是支持服务端推送,二是支持 TCP 连接复用。
使用二进制代理文本进行传输,极大提高了传输的效率
服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。
TCP 连接复用,则使用同一个 TCP 连接来传输多个 HTTP 请求,避免了 TCP 连接建立时的三次握手开销,和初建 TCP 连接时传输窗口小的问题。