HTTP协议(超文本传输协议HyperText Transfer Protocol),它是基于TCP协议的应用层传输协议,简单来说就是客户端和服务端进行数据传输的一种规则。
HTTP 最早于 1991 年发布,是 0.9 版,不过目前该版本已不再用。HTTP 目前在使用的版本主要有:
- HTTP/1.0,于 1996 年 5 月发布,引入了多种功能,至今仍在使用当中。
- HTTP/1.1,于 1997 年 1 月发布,持久连接被默认采用,是目前最流行的版本。
- HTTP/2 ,于 2015 年 5 月发布,引入了服务器推送等多种功能,是目前最新的版本。
UPI是由某个协议方案表示的资源定位标识符(协议方案是指访问资源所使用的协议类型名称,如http)
URI用字符串标识某一互联网资源,表示资源地址(在互联网上所处的位置),URI用于标识各种网络资源的在网络中所处的位置(如ftp,http等)。
URL(统一资源定位符)作为web浏览器等访问web页面时输入的网页地址,只标识web页面资源,所以URL是URI的子集。
URI要使用涵盖全部必要信息的URI、绝对URL以及相对URL。相对URL是指从浏览器中基本URI处理的URL,绝对URI格式:
图1
应用http协议是,必定是一端担当客户端角色,另一端担当服务器端角色。HTTP协议规定,请求从客户端发出,最后服务器处理请求并返回响应内容。即先从客户端开始建立通信的,服务器端在没有接收到请求之前不会发送响应。
持久链接节省通信量
HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接。随着页面内容的丰富,一个页面可能包含多张图片或其他资源,每次请求都会造成TCP连接的建立和断开,增加通信量的开销。为解决该问题,HTTP/1.1及部分HTTP1.0协议规定了HTTP keep-alive持久连接方法。只要任一端没有明确提出断开链接,则保持TCP连接状态。
图2
持久连接的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载,同时,使得HTTP请求和响应能够更早的结束,加快了web页面的响应速度。
管线化
管线化:同时并行发送多个请求。
持久化连接使得多数请求以管线化方式发送成为可能。之前是发送请求后需等待收到响应才发送下一个请求。
使用Cookie 管理状态
HTTP协议是无状态的,不对之前发生过的请求和响应的状态进行管理,即无法根据之前的状态进行本次的请求处理。比如无法判断登陆验证,于是引入Cookie技术,通过在请求和响应报文中添加cookie信息来管理客户端的状态。
Cookie会根据服务器发送的响应报文中一个叫Set-Cookie的首部字段信息,通知客户端保存Cookie值,当下次客户端再往该浏览器发送请求时,客户端会自动在去请求报文中加入Cookie值再发送。服务器端接收到请求中的Cookie值时,通过对比处理之前的记录,查出是哪一个客户端发送过来的状态信息
HTTP 请求
HTTP 请求由三部分组成:
- 请求行:包含请求方法、请求地址和 HTTP 协议版本
- 消息报头:包含一系列的键值对(请求报头)
- 请求正文(可选):注意和消息报头之间有一个空行(请求实体)
如图所示:
图3
下面是一个 HTTP GET 请求的例子:
GET /index.html HTTP/1.1Host: httpbin.orgConnection: keep-aliveCache-Control: max-age=0Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Encoding: gzip, deflate, sdch, brAccept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4Cookie: _ga=GA1.2.475070272.1480418329; _gat=1复制代码
请求行:
GET /index.html HTTP/1.1
其中,GET 是请求方法,表示从服务器获取资源;/index.html 是一个请求地址;HTTP/1.1 表明 HTTP 的版本是 1.1。
请求行后面的一系列键值对就是消息报头:
- Host 是请求报头域,用于指定被请求资源的 Internet 主机和端口号,它通常从 HTTP URL 中提取出来;
- Connection 表示连接状态,keep-alive 表示该连接是持久连接(persistent connection),即 TCP 连接默认不关闭,可以被多个请求复用,如果客户端和服务器发现对方有一段时间没有活动,就可以主动关闭连接;
- Cache-Control 用于指定缓存指令,它的值有 no-cache, no-store, max-age 等,max-age=秒表示资源在本地缓存多少秒;
- User-Agent 用于标识请求者的一些信息,比如浏览器类型和版本,操作系统等;
- Accept 用于指定客户端希望接受哪些类型的信息,比如 text/html, image/gif 等;
- Accept-Encoding 用于指定可接受的内容编码;
- Accept-Language 用于指定可接受的自然语言;
- Cookie 用于维护状态,可做用户认证,服务器检验等,它是浏览器储存在用户电脑上的文本片段;
HTTP 响应
HTTP 响应与 HTTP 请求相似,由三部分组成:
- 状态行:包含 HTTP 协议版本、状态码和状态描述,以空格分隔
- 响应头:即消息报头,包含一系列的键值对(响应报头)
- 响应正文:返回内容,注意和响应头之间有一个空行(响应主体)
如图所示:

图4
下面是一个 HTTP GET 请求的响应结果:
HTTP/1.1 200 OK Server: nginx Date: Tue, 29 Nov 2016 13:08:38 GMT Content-Type: application/json Content-Length: 203 Connection: close Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true { "args": {}, "headers": { "Host": "httpbin.org", "User-Agent": "Paw/2.3.1 (Macintosh; OS X/10.11.3) GCDHTTPRequest" }, "origin": "13.75.42.240", "url": "https://httpbin.org/get" }复制代码
上面的第一行就是一个状态行:
HTTP/1.1200 OK
其中,200 是状态码,表示客户端请求成功,OK 是相应的状态描述。
状态行后面的一系列键值对就是消息报头,即响应头:
Server: nginxDate: Tue, 29 Nov 201613:08:38 GMTContent-Type: application/jsonContent-Length: 203Connection: closeAccess-Control-Allow-Origin: *Access-Control-Allow-Credentials: true复制代码
其中:
- Server 包含了服务器用来处理请求的软件信息,跟请求报头域 User-Agent 相对应;
- Content-Type 用于指定发送给接收者(比如浏览器)的响应正文的媒体类型,比如 text/html, text/css, image/png, image/jpeg, video/mp4, application/pdf, application/json 等;
- Content-Length 指明本次回应的数据长度;
HTTP 请求方法
HTTP 通过不同的请求方法以多种方式来操作指定的资源,常用的请求方法如下表:
方法
|
描述
|
GET
|
从服务器获取指定(请求地址)的资源的信息,它通常只用于读取数据(像数据库查询一样,不会对资源进行修改)
|
POST
|
向指定资源提交数据(比如提交表单,上传文件),请求服务器进行处理。数据被包含在请求正文中,这个请求可能会创建新的资源或更新现有的资源。
|
PUT
|
通过指定资源的唯一标识(在服务器上的具体存放位置),请求服务器创建或更新资源。
|
DELETE
|
请求服务器删除指定资源。
|
HEAD
|
与 GET 方法类似,从服务器获取资源信息,和 GET 方法不同的是,HEAD 不含有呈现数据,仅仅是 HTTP 头信息。HEAD 的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获得资源的元信息(或元数据)。
|
OPTIONS
|
该方法可使服务器传回资源所支持的所有 HTTP 请求方法。
|
TRACE
|
让服务器将受到的请求信息回送给客户端,主要用于测试或诊断,查询出传送过程中如何被加工修改(由于容易受到XST跨站追踪攻击,一般不用该方法)
|
CONNECT
|
要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。主要使用SSL(安全套接层)和TLS(传输安全)协议把通信内容加密后经网络隧道传输
|
比较 POST 和 PUT
注意到,POST 和 PUT 都可用于创建或更新资源,然而,它们之间还是有比较大的区别:
- POST 所对应的 URI 并非创建的资源本身,而是资源的接收者,资源本身的存放位置由服务器决定;而 PUT 所对应的 URI 是要创建或更新的资源本身,它指明了具体的存放位置
往某个站点添加一篇文章,如果使用 POST 来创建资源,可类似这样:
POST /articles HTTP/1.1{ "author": "ethan", "title": "hello world", "content": "hello world"}复制代码
在上面,POST 对应的 URI 是 /articles,它是资源的接收者,而非资源的标识,如果资源被成功创建,服务器可以返回 201 Created 状态以及新建资源的位置,比如:
HTTP/1.1201 CreatedLocation: /articles/abcdef123复制代码
我们如果知道新建资源的标识符,可以使用 PUT 来创建资源,比如:
PUT /articles/abcdef234 HTTP/1.1{ "author": "peter", "title": "hello world", "content": "hello world"}复制代码
在上面,PUT 对应的 URI 是 /articles/abcdef234,它指明了资源的存放位置,如果资源被成功创建,服务器可以返回 201 Created 状态以及新建资源的位置,比如:
HTTP/1.1201 CreatedLocation: /articles/abcdef234复制代码
- 使用 PUT 更新某一资源,需要更新资源的全部属性;而使用 POST,可以更新全部或一部分值
比如使用 PUT 更新地址为 /articles/abcdef234 的文章的标题,我们需要发送所有值:
PUT /articles/abcdef234 HTTP/1.1{ "author": "peter", "title": "hello python", "content": "hello world"}复制代码
而使用 POST,可以更新某个域的值:
POST /articles/abcdef234 HTTP/1.1{ "title": "hello python"}复制代码
- POST 是不幂等的,PUT 是幂等的,这是一个很重要的区别
HTTP 方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用,注意这里是副作用,而不是返回结果。
GET 方法用于获取资源,不会改变资源的状态,不论调用一次还是多次都没有副作用,因此它是幂等的;DELETE 方法用于删除资源,有副作用,但调用一次或多次都是删除同个资源,产生的副作用是相同的,因此也是幂等的;POST 是不幂等的,因为两次相同的 POST 请求会在服务器创建两份资源,它们具有不同的 URI;PUT 是幂等的,对同一 URI 进行多次 PUT 的副作用和一次 PUT 是相同的。
状态码:
是一个三位的数字,常见的状态码有以下几类:
- 1XX 消息 -- 请求已被服务接收,正在处理(信息状态码)
- 2XX 成功 -- 请求正常处理完毕(成功状态码)
- 200 OK
- 201 Created 已创建
- 202 Accepted 接收
- 203 Non-Authoritative Information 非认证信息
- 204 No Content 无内容,表示服务器已成功处理请求,但返回的响应中不包含主体内容(返回204响应,浏览器页面不更新)
- 206 Partial Content 部分内容,表示客户端进行了范围请求,服务器成功执行了请求,响应报文中包含了由Content-Range指定范围的实体内容
- 3XX 重定向 -- 需执行某些特殊处理来正确处理请求(重定向状态码)
- 301 Moved Permanently 永久重定向,表示请求的资源已被分配新的URL,希望之后使用新的URL来处理资源
- 302 Moved Temporarily 临时重定向,表示请求的资源已被分配新的URL,希望之后使用的URL来处理资源,但新分配的URL是临时的
- 303 See Other 浏览其他,表示请求对应地资源处在于另一个URL上,明确表示应该使用get方法获取资源
- 304 Not Modified 文件未修改,可以直接使用缓存的文件,当客户端已缓存了目标资源但不确定该缓存资源是否是最新版本时, 就会在请求中附带条件。 服务器会读取到附带条件判断出客户端缓存的资源是否最新,如果是的话,服务器就会返回HTTP/304 Not Modified响应头, 但没有响应体.客户端收到304响应后,就会从本地缓存中读取对应的资源。另一种情况是,如果服务器认为客户端缓存的资源已经过期了,那么服务器就会返回HTTP/200 OK响应,响应体就是该资源当前最新的内容.客户端收到200响应后,就会用新的响应体覆盖掉旧的缓存资源.
- 305 Use Proxy 使用代理
- 307 Temporary Redirect 临时重定向,表示请求的资源已被分配新的URL,希望之后使用的URL来处理资源,但新分配的URL是临时的,且禁止Post请求转换为Get请求。
- 4XX 请求错误 -- 请求含有词法错误或者服务器无法处理请求(客户端错误状态码),表明错误的原因发生在客户端
- 400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解,需修改内容后重新发送请求
- 401 Unauthorized 请求未经授权,需要有通过HTTP认证的认证信息(若之前已进行过1次请求,则表示用户认证失败),同时,返回的401响应中必须包含一个适用于被请求资源的WWW-Authenticate首部来质询用户信息(即浏览器初次接收到401响应时会弹出认证用的对话窗口)
- 403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因,比如未获得文件系统的访问授权,访问权限出现问题等
- 404 Not Found 请求的资源不存在,例如,输入了错误的URL,也可以在服务器拒绝请求且不愿说明原因时使用
- 5XX 服务器错误 -- 服务器处理请求出错(服务器错误状态码),表示错误的原因发生在服务器端
- 500 Internal Server Error 服务器在执行请求时发生了错误。
- 503 Service Unavailable 服务器当前暂时处于超负荷或停机维护状态,不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常
- 504 Gateway Time-out 网关超时
HTTP 特点
- 客户端/服务器模式
- 简单快速:客户端向服务器请求服务时,通过传送请求方法、请求地址和数据体(可选)即可
- 灵活:允许传输任意类型的数据对象,通过 Content-Type 标识
- 无状态:对事物处理没记忆能力
小结
- HTTP 是在网络上传输 HTML 的协议,用于浏览器和服务器的通信,默认使用 80 端口。
- URL 地址用于定位资源,HTTP 中的 GET, POST, PUT, DELETE 用于操作资源,比如查询,增加,更新等。
- GET, PUT, DELETE 是幂等的,POST 是不幂等的。
- POST VS PUT
- 使用 PUT 创建资源需要提供资源的唯一标识(具体存放位置),POST 不需要,POST 的数据存放位置由服务器自己决定
- 使用 PUT 更新某一资源,需要更新资源的全部属性;而使用 POST,可以更新全部或一部分值
- POST 是不幂等的,PUT 是幂等的,这是一个很重要的区别
- GET 可提交的数据量受到 URL 长度的限制,HTTP 协议规范没有对 URL 长度进行限制,这个限制是特定的浏览器及服务器对它的限制。
- 理论上讲,POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制,出于安全考虑,服务器软件在实现时会做一定限制。
参考资料
超文本传输协议

