本文详细讲解 HTTP 协议的概念,各个部分的概念,使用 Fiddler 工具抓取 HTTP Request 和 HTTP Response 等。

1. 概念

HTTP 协议,即超文本传输协议(Hypertext transfer protocol)。是一种详细规定了浏览器和万维网(WWW = World Wide Web)服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议;它可以使浏览器更加高效,使网络传输减少;目前我们使用的是HTTP/1.1 版本。

2. 在 TCP/IP 协议中的位置

HTTP协议通常承载于TCP协议之上,有时也承载于TLS或SSL协议层之上,这个时候,就成了我们常说的HTTPS;如下图:

http_1

HTTP默认的端口号为80,HTTPS的端口号为443。

3. 特点

3.1 支持客户/服务器模式。
3.2 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.3 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。
3.4 无连接:限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
3.5 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

4. 工作流程

一次HTTP操作称为一个事务,其工作过程可分为四步:

(1) 首先客户机与服务器需要建立连接。只要单击某个超级链接,HTTP 的工作开始。
(2) 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息包括请求修饰符、客户机信息和可能的内容。
(3) 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容。
(4) 客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上,然后客户机与服务器断开连接。

5. 使用 Fiddler 抓包

打开 Fiddler 软件,然后打开 www.minhow.com 域名,查看 Fiddler 的信息如下图:

http_2

从图可以看出,请求和响应的内容。接下来详细介绍各部分的内容。

6. HTTP协议基础

6.1 HTTP协议基础 — URL

URL (URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息)的格式如下:
http://host[“:”port][abs_path]
http 表示要通过HTTP协议来定位网络资源;host 表示合法的Internet主机域名或者IP地址;port指定一个端口号,为空则使用缺省端口80;abs_path 指定请求资源的 URI ;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。

6.2 HTTP协议基础 — 请求

请求由三部分组成,分别是:请求行、消息报头、请求正文。

请求行

以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF
其中 Method 表示请求方法;Request-URI 是一个统一资源标识符;HTTP-Version 表示请求的HTTP协议版本;CRLF 表示回车和换行。

请求方法有多种,各个方法的解释如下:

OPTIONS: 返回服务器针对特定资源所支持的 HTTP 请求方法。也可以利用向 Web 服务器发送’*’的请求来测试服务器的功能性。
HEAD: 向服务器索要与 GET 请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。
GET: 向特定的资源发出请求。注意:GET 方法不应当被用于产生“副作用”的操作中,例如在 web 中。其中一个原因是 GET 可能会被网络蜘蛛等随意访问。
POST: 向指定资源提交数据进行处理请求(例如提交表单或者上传文件);数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
PUT: 向指定资源位置上传其最新内容。
DELETE: 请求服务器删除 Request-URI 所标识的资源。
TRACE: 回显服务器收到的请求,主要用于测试或诊断。
CONNECT: HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
PATCH: 用来将局部修改应用于某一资源,添加于规范 RFC5789。

HEAD 方法与 GET 方法几乎是一样的,对于 HEAD 请求的回应部分来说,它的 HTTP 头部中包含的信息与通过 GET 请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到 Request-URI 所标识的资源的信息。

请求报头

请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。

常用的请求报头:
Accept: 请求报头域用于指定客户端接受哪些类型的信息;例如:Accept:text/html,表明客户端希望接受html文本。
Accept-Charset:请求报头域用于指定客户端接受的字符集;例如:Accept-Charset:iso-8859-1,gb2312.如果在请求消息中没有设置这个域,缺省是任何字符集都可以接受。
Accept-Encoding: 请求报头域类似于 Accept,但是它是用于指定可接受的内容编码;例如:Accept-Encoding:gzip.deflate,如果请求消息中没有设置这个域服务器假定客户端对各种内容编码都可以接受。
Accept-Language: 请求报头域类似于 Accept,但是它是用于指定一种自然语言;例如:Accept-Language:zh-cn,如果请求消息中没有设置这个报头域,服务器假定客户端对各种语言都可以接受。
Authorization:请求报头域主要用于证明客户端有权查看某个资源。当浏览器访问一个页面时,如果收到服务器的响应代码为401(未授权),可以发送一个包含 Authorization 请求报头域的请求,要求服务器对其进行验证。
Host: 请求报头域主要用于指定被请求资源的 Internet 主机和端口号,它通常从 HTTP URL 中提取出来的;例如:在浏览器中输入:http://www.minhow.com;浏览器发送的请求消息中,就会包含 Host 请求报头域,如下:
Host:www.minhow.com
Connection:例如:Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Connection: close 代表一个Request完成后,客户端和服务器之间用于传输HTTP数据的TCP连接会关闭,当客户端再次发送Request,需要重新建立TCP连接。
此处使用缺省端口号80,若指定了端口号,则变成:Host:www.minhow.com:指定端口号。
User-Agent:我们上网登陆论坛的时候,往往会看到一些欢迎信息,其中列出了你的操作系统的名称和版本,你所使用的浏览器的名称和版本,这往往让很多人感到很神奇,实际上,服务器应用程序就是从 User-Agent 这个请求报头域中获取到这些信息。User-Agent 请求报头域允许客户端将它的操作系统、浏览器和其它属性告诉服务器。不过,这个报头域不是必需的,如果我们自己编写一个浏览器,不使用 User-Agent 请求报头域,那么服务器端就无法得知我们的信息了。
Cookie:最重要的请求头之一, 将cookie的值发送给HTTP服务器。

6.3 HTTP协议基础 — 响应

在接收和解释请求消息后,服务器返回一个HTTP响应消息;也是由三个部分组成,分别是:状态行、消息报头、响应正文。

状态行

HTTP-Version, Status-Code, Reason-Phrase,
其中,HTTP-Version 表示服务器HTTP协议的版本;Status-Code 表示服务器发回的响应状态代码;Reason-Phrase 表示状态代码的文本描述。
状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:
1xx:指示信息–表示请求已接收,继续处理
2xx:成功–表示请求已被成功接收、理解、接受
3xx:重定向–要完成请求必须进行更进一步的操作
4xx:客户端错误–请求有语法错误或请求无法实现
5xx:服务器端错误–服务器未能实现合法的请求
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

响应报头

响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。常用响应报头如下:

Allow:服务器支持哪些请求方法(如GET、POST等)。
Date:表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的时间表示世界标准时,换算成本地时间,需要知道用户所在的时区。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦
Expires:指明应该在什么时候认为文档已经过期,从而不再缓存它,重新从服务器获取,会更新缓存。过期之前使用本地缓存。HTTP1.1 的客户端和缓存会将非法的日期格式(包括0)看作已经过期。为了让浏览器不要缓存页面,我们也可以将 Expires 实体报头域,设置为0。
例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT
P3P:用于跨域设置Cookie, 这样可以解决iframe跨域访问cookie的问题。
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR。
Set-Cookie:非常重要的 header, 用于把 cookie 发送到客户端浏览器,每一个写入cookie都会生成一个Set-Cookie。
Content-Type:WEB 服务器告诉浏览器自己响应的对象的类型和字符集。Servlet 默认为 text/plain,但通常需要显式地指定为text/html。由于经常要设置 Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
例如:Content-Type:text/html;charset=utf-8。
Content-Length:指明实体正文的长度,以字节方式存储的十进制数字来表示。在数据下行的过程中,Content-Length 的方式要预先在服务器中缓存所有数据,然后所有数据再一股脑儿地发给客户端。只有当浏览器使用持久 HTTP 连接时才需要这个数据。
例如: Content-Length: 19847
Content-Encoding:WEB 服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。
例如:Content-Encoding:gzip
Content-Language:WEB 服务器告诉浏览器自己响应的对象所用的自然语言。没有设置该域则认为实体内容将提供给所有的语言阅读。
Server:指明 HTTP 服务器用来处理请求的软件信息。例如:Server: Microsoft-IIS/7.5、Server:Apache-Coyote/1.1。此域能包含多个产品标识和注释,产品标识一般按照重要性排序。
X-AspNet-Version:如果网站是用ASP.NET开发的,这个header用来表示ASP.NET的版本。
例如: X-AspNet-Version: 4.0.30319
X-Powered-By:表示网站是用什么技术开发的。
例如: X-Powered-By: PHP 7.0
Location:用于重定向一个新的位置,包含新的URL地址。表示客户应当到哪里去提取文档。Location 通常不是直接设置的,而是通过HttpServletResponse 的 sendRedirect 方法,该方法同时设置状态代码为302。Location 响应报头域常用在更换域名的时候。
WWW-Authenticate :该响应报头域必须被包含在401(未授权的)响应消息中,客户端收到401响应消息时候,并发送 Authorization 报头域请求服务器对其进行验证时,服务端响应报头就包含该报头域。

7. 总结

现在 web 程序的开发技术越来越多,开发的语言也呈现百家争鸣的局面,如:ASP.NET、PHP、JSP、Perl、AJAX 等等。 无论 Web 技术在未来如何发展,理解 HTTP 基本通信协议,对于 Web 的开发也是非常重要。

最后更新: 2017年11月19日 20:17

原始链接: http://blog.minhow.com/articles/http/protocol-specification/

× 请我吃糖~
打赏二维码