HTTP 报文的组成部分

HTTP 报文是简单的格式化数据块。如图一所示,每条报文都包含一条来客户端的请求,或者一条来自客户端的响应。它们由三个部分组成:对报文进行描述的起始行start line)、包含属性的首部header)块,以及可选的,包含数据的主体body)部分。

simple_res_msg
图一:HTTP 报文的三个部分

起始行与首部就是由行分隔的 ASCII 文本。每行都以一个由两个字符组成的行终止序列作为结束,其中包括一个回车符(ASCII 码 13)和一个换行符(ASCII 码 10)。这个行终止符可以写作 CRLF。注意:尽管 HTTP 规范中说明应该用 CRLF 来表示行终止,但稳健的做法也应该接受单个换行符作为行的终止。有些老的,或不完整的 HTTP 应用程序并不总是既发送回车符,又发送换行符。

实体的主体或报文的主体是一个可选的数据块。与起始行和首部不同的是,主体中要k以包含文本或二进制数据,也可以为空。

在图一中,首部给出了一些与主体有关的信息。Content-Type 行说明了主体是什么——在这个图中,就是纯文本文档。Content-Length 行说明了主体有多大,在这里就只有 19 个字符。


一、报文的语法

所有的 HTTP 报文都可以分为两类:请求报文request message)和响应报文response message)。请求报文会向 Web 服务器请求一个动作。响应报文会将请求的结果返回客户端。请求与响应报文的基本报文结构相同。图二显示了获取一张 GIF 图片所需要的请求和响应报文。

http_req_res_msg_event
图二:包含请求与响应报文的 HTTP 事务

这就是请求报文的格式:

这是响应报文的格式(注意:只有起始行的语法有所不同):

下面是对各部分的简要描述:

方法(method)
客户端希望服务器对资源执行的动作。是一个单独的词,比如 GET,POST 或者 HEAD。
请求 URL (request-URL)
用来命名资料的完整 URL,或者 URL 的路径部分。如果直接与服务器进行对话,只要 URL 的路径部分是资源的绝对路径,通常就不会有什么问题——服务器可以假定自己是 URL 的主机/端口。
版本(version)
报文所使用的 HTTP 版本,其格式看起来是这样的:HTTP/<major>.<minor>。其中主版本号major)与次版本号minor)都是整数。
状态码(status-code)
这三位数字描述了请求过程中所发生的情况。每个状态码的第一位数字用于描述状态的一般类别(“成功”、“出错”等)。
原因短语(reason-phrase)
数字状态码的可读版本,包含行终止序列之前的所有文本。原因短语只对人类有意义。因此,比如说,尽管响应行HTTP/1.0 200 NOT OKHTTP/1.0 200 OK中原因短语的含义不同,但同样都会被当作成功的标志。
首部(header)
可以有零个或多个首部,每个首部都包含一个名字,后面跟着一个英文冒号(:),然后是一人可选的空格,接着是一个值,最后是一个 CRLF。首部是由一个空行(CRLF)结束的,表示了首部列表的结束和实体主体部分的开始。有些 HTTP 版本,比如 HTTP/1.1,要求有效的请求或响应报文中必须包含特定的道部。
实体的主体部分(entity-body)
实体的主体部分包含了一个由任意数据结成的数据块。并不是所有的报文都包含实体的主体部分,有时,报文只是以一个 CRLF 结束。
res_req_sample
图三:假想的请求报文与响应报文

注意,一组 HTTP 首部总是应该以一个空行(仅有 CRLF)结束,甚至即使没有首部和实体的主体部分也应该如此。但由于历史原因,很多客户端和服务器都在没有实体的主体部分时,(错误的)省略了最后的 CRLF。为了与这些流行但不符合规则的实现兼容,客户端和服务器都应该接受那些没有最后那个 CRLF 的报文。


二、起始行

所有的 HTTP 报文都以一个起始行作为开始。请求报文的起始行说明了要做些什么。响应报文的起始行说明发生了什么

1. 请求行
求报文请求服务器对资源进行一些操作。请求报文的起始行,或称为请求行,包含了一个方法和一个请求 URL,这个方法描述了服务器应该执行的操作,请求 URL 描述了要对哪个资源执行这个方法。请求行中还包含 HTTP 的版本,用来告诉服务器,客户端使用的是哪种 HTTP。所以这些字段都由空格分隔。
2. 响应行
响应报文承载了状态信息和操作产生的所有结果数据,将其返回给客户端。响应报文的起始行,或称为响应行,包含了响应报文使用的 HTTP 版本,数字状态码,以及描述操作状态的原因短语(文本形式)。所有这些字段也都由空格分隔。
3. 方法
请求的起始行以方法作为开始,方法用来告知服务器要做些什么。比如在行 GET /test/hi-there.txt HTTP/1.1 中,方法就是GET。
4. 状态码
方法是用来告诉服务器做什么事情的,状态码则是用来告诉客户端发生了什么事情。状态码位于响应的起始行中。比如在行 HTTP/1.1 200 OK 中,状态码就是 200。
客户端向一个 HTTP 服务器发送请求报文时,会发生很多事情。幸运的话,请求会成功完成。但你不会总是那么幸运的。服务器可能会告诉你无法找到所请求的资源你没有访问资源的权限,或者资源被移到了其它地方。
状态码是在每条响应报文的起始行中返回的。会返回一个数字状态和一个可读的文本状态(reason-phrase)。数字码便于程序进行差错处理,而原因短语则更全球人们理解。
可以通过三位数字代码对不同状态码进行分类。2 开头的代码表示成功,3 开头的代码表示资源已经被移走,4 开头的代码表示客户端的请求出错,5 开头的代码表示服务器出错。
5. 原因短语
原因短语是响应起始行的最后一个组件。它为状态码提供了文本形式的解释。比如在行 HTTP/1.1 200 OK 中,OK 就是短语。
原因短语和状态码是成对出现的。原因短语是状态码的可读版本,应用程序开发者将其传递给用户,用以说明在请求期间发生了什么情况。HTTP 规范没有硬性规定原因短语的形式,所以使用都可以自定义。
6. 版本号
版本号会以 HTTP/x.y 的形式出现在请求和响应报文的起始行中。为 HTTP 应用程序提供了一种将自己所遵循的协议版本告知对方的方式。
使用版本号的目的是为了使用 HTTP 的应用程序提供一种线索,以便互相了解对方的能力与报文格式。在使用与 HTTP 1.1 的服务器进行通信的 HTTP 2.0 客户端应该知道,它不能使用任何新的 2.0 特性,因为使用老版本协议的服务器很可能无法实现这些特性。

三、首部

前一小节的重点是请求和响应报文的第一行(方法,状态码,原因短语和版本号)。跟在起始行后面的就是零个,一个或多个 HTTP 首部字段(详见图三)。

HTTP 首部字段向请求和响应报文中添加了一些附加信息。本质上说,它们只是一些名/值对的列表。比如,下面的首部行会向 Content-Length 首部字段赋值 19:Content-Length:19

1. 首部分类

HTTP 规范定义了几种首部字段。应用程序也可以随意发明自己所用的首部。HTTP 首部可以分为以下几类。

通用首部
既可以出现在请求报文中,也可以出现在响应报文中
请求首部
提供更多有关请求的信息
响应首部
提供更多有关响应的信息
实体首部
描述主体的长度和内容,或者资源本身
扩展首部
规范中没有定义的新首部

每个 HTTP 首部都有一种简单的语法:名字后面跟着英文冒号(:),然后跟上可选的空格,再跟上字段值,最后是一个 CRLF。

2. 首部延续行

将长的首部行分为多行可以提高可读性,多出来的每行前面至少有一个空格或制表符。例如:

在这个例子中,响应报文里包含了一个 Server 首部,其值被划分了多个延续行。该首部的完整值为Test Server Version 1.0


四、实体的主体部分

HTTP 报文的第三部分是可选的实体主体部分。实体的主体是 HTTP 报文的负荷。就是 HTTP 要传输的内容。

HTTP 报文可以承载很多类型的数字内容:图片,视频,HTML 文档等等。

发表评论

电子邮件地址不会被公开。 必填项已用*标注