1. 简介
HTTP 协议是 Hyper Text Transfer Protocol(超文本传传输协议)的缩写,是用于从万维网服务器传输超文本到本地浏览器的传送协议。HTTP 通常架构在 TCP 传输协议之上,如下图所示。有时出于安全的考虑,HTTP 还需要经过 TLS 或 SSL 层的封装,架构在 SSL 层之上的 HTTP 协议通常称为 HTTPS(Hypertext Transfer Protocol over Secure Socket Layer)协议。
HTTP 协议是一个无状态的协议,即客户端向服务器端发送出请求时,服务器并没有存储关于该客户端和请求的任何状态信息。即便同一个客户端在几秒钟内再次请求通过一个对象,服务器也不会响应说自己刚刚给它发送了这个对象。相反,服务器会重新发送这个对象,因为它已经彻底忘记自己早先做过什么了,同一个客户端的这次请求和上次请求没有任何关系。
HTTP 1.1 支持持续连接机制,即客户端和服务端建立 TCP 连接后,后续相关联的 HTTP 请求可以重复利用已经建立起来的 TCP 连接,不仅整个 Web 页面(包括基本的 HTML 文件和其他对象)可以使用这个持续的 TCP 连接来完成 HTTP 请求和响应,而且同一个服务器内的多个 Web 页面也可以通过同一个持续 TCP 连接来请求和响应。通常情况下,这个持续的 TCP 连接会在空闲一段特定的时间后关闭,而这个最大空闲时间是可以设置的。
持续连接的 TCP 连接一般可以分为两类:带流水线和不带流水线。在不带流水线的持续连接下,用户的 HTTP 请求只能在上一个请求得到响应后才能发出;带流水线的持续连接则没有这个限制,客户端在 Web 页面发现引用时就可以发起 HTTP 请求,无须考虑上一个请求的响应消息是否已经收到。
不带流水线的持续性连接示意图
带流水线的持续性连接示意图
HTTP 1.1 中,客户端和服务器都默认支持持续的带流水线的 TCP 连接。如果客户端使用 HTTP 1.1 协议而又不希望使用持续的 TCP 连接,则可以将请求消息中的 Connection 头的值设置为 close;同理,使用 HTTP 1.1 的服务器如果不希望使用持续的 TCP 连接,也可以将响应消息中的 Connection 头的值设置为 close。
2. 基本工作方式
HTTP 协议是一个标准的 "请求+响应" 协议,即客户端与服务器建立连接后,就向服务器发送一个 HTTP 请求,告诉服务器客户要操作什么,对什么进行操作以及怎么操作。服务器在完成请求分析后,通知客户端能不能做,为什么不能做。
2.1 HTTP 之请求消息 Request
客户端发送一个 HTTP 请求到服务器的请求消息包括以下格式:
- 请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
请求行以一个方法符号开头,以空格分开,后面跟着请求的 URI 和协议的版本。
Get 请求例子,使用 Charles 抓取的 request:
GET /562f25980001b1b106000338.jpg HTTP/1.1
Host: img.mukewang.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
Accept: image/webp,image/*,*/*;q=0.8
Referer: http://www.imooc.com/
Accept-Encoding: gzip, deflate, sdch
Accpet-Language: zh-CN,zh;q=0.8
- 第一部分:请求行,用来说明请求类型,要访问的资源以及所使用的 HTTP 版本。
GET 说明请求类型为 GET,/562f25980001b1b106000338.jpg 为要访问的资源,该行的最后一部分说明使用的是 HTTP 1.1 版本。
- 第二部分:请求头部,紧接着请求行(即第一行)之后的部分,用来说明服务器要使用的附加信息。
从第二行起 为请求头部,HOST 将指出请求的目的地。User-Agent,服务器端和客户端脚本都能访问它,它是浏览器类型检测逻辑的重要基础。该信息由你的浏览器来定义,并且在每个请求中自动 发送等等。
- 第三部分:空行,请求头部后面的空行是必须的。
即使第四部分的请求数据为空,也必须有空行。
- 第四部分:请求数据也叫主体,可以添加任意的其他数据。
这个例子的请求数据为空。
POST 请求例子,使用 Charles 抓取的 request:
POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
name=Professional%20Ajax&publisher=Wiley
- 第一部分:请求行,第一行说明是 POST 请求,以及 HTTP 1.1 版本
- 第二部分:请求头部,第二行至第六行
- 第三部分:空行,第七行是空行
- 第四部分:请求数据,第八行
2.1.1 请求方式
- GET:请求获取由 URI 所指定的资源。这个资源通常包含在响应消息的实体中返回给请求者。
- HEAD:此方法和 GET 方法类似,只不过服务器不能在响应消息里包含资源内容,只返回头信息。
- POST:请求源服务器将请求消息中包含的实体作为请求资源的一个从属物。POST 可以完成以下功能:
- 对服务器上已存在的资源进行注释;
- 发布消息给一个公告板、新闻组、邮件列表、或者相似的文章组;
- 提供一个数据块,如提交一个表单给一个数据处理过程;
- 通过追加操作来扩展数据库。
- PUT:请求服务器把请求里的实体存储为 URI 所标的资源。如果 URI 所指定的资源已经在源服务器上存在,那么此请求里的实体内容应该是此 URI 所指定资源的修改版本;如果请求 URI 指定的资源不存在,源服务器根据请求里的实体内容创建一个使用此 URI 所标识的资源。
- DELETE:请求源服务器删除 URI 指定的资源。此方法可能会在源服务器上被人为干涉,所以服务器返回客户端的状态码不一定成功。
- TRACE:用于触发远程的、应用层的请求响应回路。这个方法通常让客户端测试其连到服务器的网络通路,收到请求的每一个代理服务器和网关服务器不断转发请求,同时向客户端发出响应消息,直到最后的接收者。TRACE 请求不能包含实体。
- CONNECT:用于一个代理服务器,使其提供隧道服务。
2.2 HTTP 之响应消息 Response
一般情况下,服务器接收并处理客户端发过来的请求后会返回一个 HTTP 的响应消息。
HTTP 响应也由 四个部分组成,分别是:状态行、消息报头、空行和响应正文。
例子:
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8
<html>
<head></head>
<body>
<!--body goes here-->
</body>
</html>
- 第一部分:状态行,由 HTTP 协议版本号,状态码,状态消息 三部分组成。
第一行为状态行,(HTTP/1.1) 表明 HTTP 版本为 1.1 版本,状态码为 200,状态消息为 (OK)
- 第二部分:消息报头,用来说明客户端要使用的一些附加信息。
第二行和第三行为消息报头,Data:生成响应的日期和时间;Content-Type:制定了 MIME 类型和 HTML(text/html),编码类型是 UTF-8
-
第三部分:空行,消息报头后面的空行是必须的
-
第四部分:响应正文,服务器返回给客户端的文本信息。
空行后面的 html 部分为响应正文。
2.2.1 状态码
- 1xx:指示信息 -- 表示请求已接收,继续处理。
- 2xx:成功 -- 表示请求已被成功接收、理解、接受。
- 3xx:重定向 -- 要完成请求必须进行更进一步的操作。
- 4xx:客户端错误 -- 请求有语法错误或请求无法实现。
- 5xx:服务器端错误 -- 服务器未能实现合法的请求。
典型的状态号及其含义如下:
状态码 | 原因短语 | 描述 |
---|---|---|
100 | Continue | 客户端必须继续发出请求 |
200 | OK | 客户端请求成功 |
202 | Accepted | 接受和正在处理,但处理未完成 |
203 | None-Authoritative Information | 返回的信息不确定或不完整 |
206 | Partial Content | 客户端发送了带 Range 的 GET 请求,服务器端正确地返回了此范围内的数据 |
301 | Moved Permanently | 请求的数据已永久删除或永久地转移至其他地方 |
302 | Found | 指出被请求的文档已经临时移动到别处,此文档的新 URL 在 Location 响应头中给出 |
304 | Not Modified | 被缓存的版本是最新的,可以继续使用 |
400 | Bad Request | 客户端请求语法有错误,不能被服务器理解 |
401 | Unauthorized | 表示客户端访问的资源受用户名和密码的保护,提示客户端应重新发出一个带有 Authorization 头的请求信息 |
403 | Forbidden | 服务器拒绝提供服务 |
404 | Not Found | 请求的资源不存在 |
500 | Internal Server Error | 服务器内部发生错误 |
502 | Bad Gateway | 网关错误 |
503 | Server Unavailable | 服务器当前不能处理请求,一段时间后可恢复正常 |
2.3 HTTP 之头部
HTTP 的头部分类大致有 4 种:通用头,请求头,实体头以及响应头。
2.3.1 通用头
通用头不是应用于请求消息中的特定实体,而是应用于整个请求消息,通常既适用于请求消息,也适用于响应消息。 通用头有 Connection,Connection 中的 "Keep-Alive" 表明了 TCP 连接是一个持续连接。
典型的通用头如下:
- Connection:指示客户端与服务器在进行 HTTP 通信时如何处理 TCP 连接,如果 Connection 的值为 close,则表示本次 HTTP 请求响应后结束 TCP 连接;如果 Connection 的值为 Keep-Alive(HTTP 1.1 下为默认),则表示 TCP 连接一直有效。
- Date:Date 通用头域表明消息产生的日期和具体时间。
- Pragma:被用于包含特定执行指令,这些指令可能被应用于请求和响应消息传递过程中的任何接收者。最常用的为
Pragma: no-cache
,表示对请求的实体内容不予缓存。 - Transfer-Encoding:指示整个消息主体的传输编码方式,主要是为了实现在接收端和发送端之间进行安全的数据传输。比如
Transfer-Encoding: chunked
表示消息主体采用块编码的方式。 - Upgrade:客户端可以通过它表示自己希望进行协议转换(比如从 HTTP 一个版本转换到另一个版本),如果服务器同意的话会切换到这个指定的协议,这个协议一般是指应用层协议。
- Via:Via 用来指明请求和响应消息在客户端和服务器之间传递时所经过的代理和网关以及相关的中间协议。比如 HTTP 1.0 的请求消息发送给代理 A,A 使用 HTTP 1.1 将消息转发给网关 B,B 再发送给源服务器,这时源服务器看到 Via 头域为
Via: 1.0 A, 1.1 B
。 - Warning:携带相关警告信息,比如可以被代理和网关用来警告客户端所接收内容的过期状态以及警告客户端实体内容的编码格式发生了变化等。
2.3.2 请求头
请求头主要包含本请求的附加信息以及客户端的附加信息。
典型的请求头如下:
- Accept:用于指定本请求所期望的服务器返回响应的媒体类型。比如
Accept: audio/*; q=0.2, audio/basic
表明用户客户端希望接收到 audio/basic 的媒体,但也可以接受其他任何 audio 类型(audio/* 表示),但偏好程度只有 audio/basic 的 20%(这里的 q 是一个表示喜欢程度的质量参数)。 - Accept-Charset:用来指定客户端能接受什么样的字符集响应。比如
Accept-Charset: iso-8859-5
。 - Accept-Encoding:和 Accept 头相似,但 Accept-Encoding 限定的是客户端可以从服务器接收的内容编码。比如
Accept-Encoding: compress, gzip
。 - Accept-Language:和 Accept 头相似,但 Accept-Language 限定的是客户端可以从服务器接收的自然语言。比如
Accept-Language: en-us
。 - Accept-Range:指示客户端希望从服务器收到的内容的字节范围。
- Authorization:客户端的某些访问要求服务器授权,通常客户端会先在服务器的响应消息中收到包含有授权证书的 WWW-Authenticate 头,然后在需要授权的请求消息里包含一个带有这个授权证书的 Authorization 请求头。
- From:包含客户端当前操作用户的 E-mail 地址,代表的是具体的用户,而不是发出请求的主机。
- Host:标识请求资源的网络主机和端口号,Host 头的值代表源服务器或网关的命名授权,一般会在用户访问的 URL 中标明。比如对
http://www.netitv.com/i_movie/movie.shtml
的请求在 HTTP 消息里通过以下形式表示:- GET netitv.com/i_movie/movie.shtml HTTP/1.1
- Host: www.netitv.com
- 其中 www.neitv.com 就是主机名
- If-Match:与 ETag 一起用来判断已缓存的内容是否被修改过。比如,客户端在获取内容时会获取一个与内容相关的实体标签 ETag(内容变化会使 ETag 变化),下次再请求同样内容时,会在请求头的 If-Match 中包含这个 ETag,然后发给可能存有更新内容的服务器。服务器将收到的 ETag 与本地目前的 ETag 进行比较,如果匹配返回所请求内容。这种方法在断点续传的时候使用较多。
- If-None-Match:与 If-Match 用法类似,结果相反。如果 If-None-Match 中包含了 ETag 的值,服务器在进行比较后发现如果不匹配,则返回所请求的内容,否则不返回相关内容。这种方法在网页刷新的时候使用较多。
- If-Modified-Since:当客户端请求服务器判断自己缓存的内容是否变化时,可以设置 If-Modified-Since 头,如果服务器上的内容修改时间比这个头的时间值还要新,那么将返回新的内容,否则不返回。这个与 If-Unmodified-Since 类似,是用来判断资源变化的另一种方式。
- If-Unmodified-Since:与 If-Modified-Since 正好相反,如果服务器上的内容修改时间比这个头时间的值还要新,则不返回新的内容,否则返回所请求内容。
- If-Range:一般结合 Range 头一起使用。If-Range 的值可以是 ETag,也可以是具体的时间值。如果收到含有 If-Range 头的服务器发现所请求内容没有改变,则根据 Range 头指示的字节范围进行续传,否则返回整个文档内容。
- Max-Forwards:指示此 HTTP 请求可以途径的代理服务器或网关个数。每经过一个代理服务器或网关,这个值就会被减 1。如果减到 0,则代理服务器或网关将中止继续发送。
- Proxy-Authorization:与 Authorization 类似,只不过是需要代理服务器进行授权时才使用。
- Range:客户端通知服务器只需返回部分内容,以及部分内容的范围。这对于较大文档的断电续传是很有帮助的。如果客户机在一次请求中,只收到了服务器返回的部分内容,则客户端可以再发出一个带 Range 头的请求,这时服务器将会返回 Range 头值规定的那部分内容。
- Referer:告诉服务器这次请求是通过点击哪个网页上的超链接转向过来的。由于可以使用 Telnet 来仿造 HTTP 请求,所以 Referer 是不可靠的。"Referer" 是由于 HTTP 的作者拼写错误,在实际应用中沿袭下来,不可以写成正确的拼写方式 Referrer。
- User-Agent:用于指定浏览器的类型和名字,比如 Mozilla/4.0。
2.3.3 响应头
响应头包含响应的附加信息,给出了有关服务器的信息以及请求 URI 所指定资源的访问机制。
常用的响应头如下:
- Accept-Range:指明服务器对用户请求范围的接受程度。比如
Accept-Range: 100-599
。表示服务器只接受请求范围的第 100 字节到 599 个字节。 - Age:当服务器使用缓存的内容去响应请求时,用该头部表明该内容从产生到现在经过多长时间。
- ETag:对应实体内容的一个实体标签,与实体内容紧密相关,实体内容发生任何变化都会使这个头的值发生变化。
- Location:当客户端向服务器请求一个内容,但请求消息中 URI 所标识的内容发生了转移,那么接收者能将访问重定向于 Location 指示的 URI,如
Location: http://www.netitv.com/netitv/movie_1.shtml
。 - Proxy-Authenticate:此头必须被包含在 407 响应(代理认证)里。此头域值由一个 challenge 和 parameters 组成,chanllenge 指明了认证机制,而 parameters 是一些与此代理相关的参数。
- Retry-After:可以与 503 (服务不可用)响应一起使用,服务器用它来告知请求端服务不可用的时长。也可与 3xx(重定向)响应一起使用,服务器用它来告知客户端发送重定向请求之前需要等待的最小时长,比如
Retry-After: 60
。 - Server:包含了源服务器处理请求的软件信息,比如
Server: Apache
。 - Vary:指定了一些请求头,这些请求头可被服务器用来决定缓存的没有过期的内容能否被允许去响应后续相同的请求,比如请求消息发送到代理服务器,其中 Accept-Encoding 头是 "gzip",代理服务器向源服务器转发请求,源服务器给代理服务器返回响应消息,其中 Vary 头为
Vary: Accept-Encoding
,此时代理服务器将响应内容与 gzip 一起缓存。如果后续用户再向代理服务器发送请求时,并且 Accept-Encoding 头的值是 gzip,代理服务器则可以直接使用未过期的缓存内容来响应,如果 Accept-Encoding 头的值是 deflate 或者其他,则需要重新从源服务器获取。 - WWW-Authenticate:必须包含在 401(没有被认证)响应消息中,这个响应头应至少包含一个 challenge 值来标识认证方案以及一些与所请求的 URI 相关的参数。
2.3.4 实体头
实体头包含了与实体内容相关的元数据信息。
典型的实体头如下:
- Allow:指示可以使用的请求方式。比如
Allow: GET, HEAD, PUT
。 - Content-Encoding:指示实体内容以哪种方式编码。比如
Content-Encoding: gzip
。 - Content-Language:实体内容的国家语言,比如
Content-Language: zh-ch
表示简体中文。 - Content-Length:实体内容的大小,比如
Content-Length: 3495
。 - Content-Location:当实体内容的真正 URI 和请求 URI 不同时,在消息里提供这个真正的位置信息。
- Content-MD5:实体内容的 MD5 摘要算法 Base-64 值,以提供实体内容的完整性校验。服务器可以通过对实体内容进行 MD5 摘要算法与此头的值是否相同来确定接收的请求是否没有错误与改变。
- Content-Range:表示返回的内容是整个实体内容的哪个部分。比如
Content-Range: 2351-4767/8568
,表明本次响应是实体内容的第 2351 字节到第 4767 字节,8565 是实体内容的总大小。 - Content-Type:服务器在返回内容时需要告诉浏览器本响应的内容是什么类型的。HTTP 中把这种不同媒体类型的格式称为多媒体文件格式(MIME),而本实体头指出所传输实体内容的 MIME。由于 Web 服务器不知道所返回的内容文件是哪种 MIME,所以需要通过对 Web 服务器进行设置,使文件扩展名与 MIME 之间进行映射。比如
Content-Type: text/html; charset=ISO-8859-4
。 - Expires:指示当前内容在何时之后被认为过期,缓存在为客户端请求提供服务时,如果缓存内容已经过期,则不会使用此缓存内容来直接提供服务。比如
Expires: Tue. 17 Jul 2011 18:06:45 GMT
。 - Last-Modified:指定所访问内容的最后更新时间。
来源:oschina
链接:https://my.oschina.net/u/4353432/blog/3944514