http报文

http 报文

感性理解

如果说 http 是因特网的信使,那么 http 报文就是他用来搬东西的包裹。

报文流

  http 报文是在 http 应用程序之间发送的数据块,这些数据块以一些文本形式的 元信息 开头,这些信息描述了报文的内容及含义,后面跟着可选的数据部分。这些报文在客户端,服务器和代理之间流动,术语“流入”,“流出”,“上游”,“下游”都是用来描述报文方向的。

报文流入源端服务器

  http 使用术语流入(inbound)和流出(outbound)来描述事物处理的方向,报文流入源端服务器,工作完成之后,会流回用户的 Agent 代理中

报文向下游流动

  http 报文会想河水一样流动,无论是请求报文还是响应报文。所有报文都会向下游(downstream)流动。所有报文的发送者都在接收者的上游(upstream)

1.png

报文的组成部分

  http 报文是简单的格式化数据块,每条报文都包含一条来自客户端的请求,或者一条来自服务器的响应。他们由三个部分组成:起始行,首部,主体(可选)部分

  起始行和首部就是由行分隔的 ASCII 文本,每行都以一个由两个字符组成的行终止序列作为结束,其中包括一个回车符和一个换行符。这个行终止序列可以写作 CRLF。尽管 http 规范中说明应该用 CRLF 来表示行终止,但稳健的应用程序也应该接受单个换行符作为行的终止。

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

报文的语法

  所有的 http 报文都可以分为两类: 请求报文 响应报文 ,请求报文会向 web 服务器请求一个动作,响应报文会将请求的结果返回给客户端。

请求报文的格式:

<方法> <请求URL> <版本>
<首部>

<实体的主体部分>

响应报文的格式:

<版本> <状态码> <原因短语>
<首部>

<实体的主体部分>

可以看出,只是起始行的语法不同而已。

  • 方法(method):

客户端希望服务器对资源执行的动作,是一个单独的词,如 GET,HEAD,POST,稍后会做出详细解释

  • 请求 URL(request-URL)

命名了所请求资源,或者 URL 路径组件的完整 URL,在前文中已经详细阐述了 URL 语法

  • 版本(version)

报文所使用的 http 版本,其格式如下:

HTTP/<主版本号>.<次版本号>

稍后会做出详细解释

  • 状态码 (status-code)

一个三位数字,描述请求过程中所发生的情况,第一位数字用于描述一般类别(“成功”或者“出错”),稍后会做出详细解释

  • 原因短语 (reason-phrase)

数字状态码的可读版本,其 只对人类有意义 ,内容不会对请求的状态有实质的影响(状态码是唯一标准)

  • 首部 (header)

可以由 零个或多个 首部,每个首部都包含一个名字,后面跟着一个冒号,然后是一个 可选的空格 ,接着是一个值,最后是一个 CRLF。首部是由一个空行(CRLF)结束的,表示了首部列表的结束和实体主体部分的开始。有些 http 版本(如 http/1.1),要求有效的请求或响应报文中必须包含特定的首部,稍后会做出详细解释。

  • 实体的主体部分 (entity-body)

包含一个由任意数据组成的数据块,并不是所有的报文都包含实体的主体部分 ,有时报文只是以一个 CRLF 结束。我们要在相当远的未来详细解释这部分。

起始行

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

请求行

  请求报文请求服务器对资源进行一些操作,请求行(请求报文的起始行)包含了一个方法和一个请求 URL,这个方法描述了服务器应该执行的操作,请求 URL 描述了要对哪个资源执行这个方法。请求行中还包含 http 的版本,用来告知服务器客户端使用的是哪种 http

  所有这些字段都由空格符分隔。

响应行

  响应报文承载了状态信息和操作产生的所有结果数据,将其返回给客户端。响应行(响应报文的起始行)包含了响应报文使用的 http 版本,数字状态吗,以及描述操作状态的文本形式的原因短语。

  在 http/1.0 版本之前,并不要求在响应中包含响应行

方法

  请求的起始行以方法作为开始,用来告知服务器要做些什么,http 规范中定义了一组常用的请求方法,比如 GET 方法负责从服务器获取一个文档,POST 方法会向服务器发送需要处理的数据,OPTIONS 方法用于确定 web 服务器的一般功能,或者 web 服务器处理特定资源的能力。

方法 描述 是否包含主体
GET 从服务器获取一份文档
HEAD只从服务器获取文档的首部
POST向服务器发送需要处理的数据
PUT将请求的主体部分存储在服务器上
TRACE对可能经过代理服务器传送到服务器上去的报文进行追踪
OPTIONS决定可以在服务器上执行哪些方法
DELETE从服务器上删除一份文档

  并不是所有服务器都实现了上述的 7 种方法,而且优于 http 的易扩展性,其他服务器可能还会实现一些自己的请求方法,称为 扩展方法

状态码

  状态码用来告诉客户端发生了什么事情,位于响应的起始行中,比如 http/1.0 200 OK 中,状态码就是 200。

  客户端向一个 http 服务器发送请求报文时,会发生很多事情。幸运的话请求会成功完成,但并不会总是如此幸运,服务器可能会告诉你无法找到所请求的资源,你没有访问资源的权限,或者资源被移到了其他地方。

  状态码是在每条响应报文的起始行中返回的,会返回一个数字状态和一个可读的状态。数字码便于程序进行差错处理,原因短语则更便于人类理解。

  可以通过三位数字代码对不同状态码进行分类,200-299 之间表示成功,300-399 之间表示资源已被移走,400-499 之间表示客户端的请求出错,500-599 之间表示服务器出错。

整体范围 已定义范围 分类
100-199100-101 信息提示
200-299200-206 成功
300-399300-305 重定向
400-499400-415 客户端错误
500-599500-505 服务器错误

  随着协议的发展,http 规范中会正式地定义更多的状态码,如果收到了不认识的状态码,可能是作为当前协议的扩展定义的,可以根据其所处的范围,将它作为类别中一个普通的成语来处理,比如如果收到了状态码 515,就应该被认为是 5XX 类型(服务器错误)

状态码 原因短语 含义
200OK 成功,请求的所有数据都在响应体中
401Unauthorized 未授权,需要输入用户名和密码
404Not Found 未找到,服务器无法找到所请求的 URL 对应的资源

原因短语

  原因短语是响应起始行中的最后一个组件,它为状态码提供了文本形式的解释。原因短语和状态码是成对出现的,是状态码的可读版本,http 规范并没有提供任何硬性规定要求原因短语以何种形式出现。

版本号

  版本号会以 HTTP/x.y 的形式出现在请求和响应报文的起始行中,为 http 应用程序提供了一种将自己所遵循的协议版本告知对方的方式。

  使用版本号的目的是为使用 http 的应用程序提供一种线索,以便互相了解对方的能力和报文格式。它说明了应用程序所支持的最高 http 版本,但 HTTP/1.0 应用程序在解释包含 HTTP/1.1 的响应时,会认为这个响应是个 1.1 响应,而实际上这只是响应应用程序所使用的协议等级,在这些情况下,版本会在应用程序之间造成误解。

  注意, 版本号不会被当作分数来处理 ,每一个数字都会被当作一个单独的数字来处理,因此,在比较 http 版本时。每个数字都必须单独进行比较,以便确定哪个版本更高。比如,HTTP/2.22 就比 HTTP/2.3 的版本要高,因为 22 比 3 大。

首部

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

首部分类

  • 通用首部

既可以出现在请求报文中,也可以出现在响应报文中

  • 请求首部

提供更多有关请求的信息

  • 响应首部

提供更多有关响应的信息

  • 实体首部

描述主体的长度和内容,或者资源自身

  • 扩展首部

规范中没有定义的新首部

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

首部实例 描述
Date:Tue,30ct 2020 02:16:03 GMT 服务器产生响应的日期
Content-length:15040 实体的主题部分包含了 15040 字节的数据
Content-type:image/gif 实体的主体部分是一个 GIF 图片
Accept:image/gif,image/jpeg,text/html 客户端可以接受 GIF,JPEG 图片以及 HTML

首部延续行

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

实体的主题部分

  http 报文的第三部分是可选的实体主体部分。实体的主体是 http 报文的负荷,即 http 要传输的内容。http 报文可以承载很多类型的数字数据:图片,音频,视频,HTML 文档,信用卡事物,电子邮件,软件应用程序等。

版本 0.9 的报文

  http 版本 0.9 是 http 协议的早期版本,是当今 http 所拥有的请求及响应报文的鼻祖,但其协议要简单的多。

  HTTP/0.9 报文也由请求和响应组成,但请求中只包含方法和请求 URL,响应中只包含实体。它没有版本信息(它是第一个也是当时唯一的版本),没有状态码,没有原因短语,也没有首部

  这种简单协议无法提供更多的灵活性,也无法实现本文及以后描述的大部分 HTTP 特性和应用。

方法

  现在对方法进行更深入的讨论,注意:并不是每个服务器都实现了所有的方法,土狗一台服务器要与 http 1.1 兼容,那么只要为其资源实现 GET 方法和 HEAD 方法就可以了。

  即使服务器实现了所有这些方法,这些方法的使用也可能是受限的,例如,支持 DELETE 方法或 PUT 方法的服务器可能并不希望任何人都能够删除或存储资源。

安全方法

  http 定义了一组被称为安全方法的方法,GET 和 HEAD 都被认为是安全的,这意味着使用 GET 或 HEAD 请求都不会产生什么动作。

  不产生动作,意味着 http 请求不会在服务器上产生什么结果。但 安全方法不一定是什么动作都不执行的 (这方面 web 开发者有完全的自主权),使用安全方法的目的就是允许 http 应用程序开发者通知用户,什么时候会使用某个可能引发某些动作的不安全方法。

GET

  GET 是最常用的方法,通常用于请求服务器发送某个资源。http/1.1 要求服务器实现此方法。

HEAD

  HEAD 方法与 GET 方法的行为类似,但服务器在响应中只返回首部,不会返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查。使用 HEAD,可以:

  • 在不获取资源的情况下了解资源的情况(比如判断其类型)
  • 通过查看响应中的状态码,看看某个对象是否存在
  • 通过查看首部,测试资源是否被修改了

服务器开发者必须确保 HEAD 返回的首部与 GET 请求所返回的首部完全相同,遵循 HTTP/1.1 规范,就必须实现 HEAD 方法。

PUT

  与 GET 从服务器读取文档相反,PUT 方法会向服务器写入文档。有些发布系统允许用户创建 web 页面,并用 put 直接将其安装到 web 服务器上。

  PUT 方法的语义就是让服务器用请求的主体部分来创建一个由所请求的 URL 命名的新文档,或者如果这个 URL 已经存在的话,就用这个主体来代替它。

  因为 PUT 允许用户对内容进行修改,所以很多 web 服务器都要求在执行 PUT 之前,用密码登录。

POST

  POST 方法起初是用来向服务器输入数据的,实际上,通常会用它来支持 HTML 的表单,表单中填好的数据通常会被发送给服务器,然后由服务器将其发送到它要去的地方。

TRACE

  客户端发起一个请求时,它可能要穿过防火墙,代理,网关或其他一些应用程序,每个节点都有可能会修改原始的 HTTP 请求。TRACE 方法允许客户端在最终将请求发送给服务器时,看看它变成了什么样子。

  TRACE 请求会在目的服务器发起一个“环回”诊断。行程最后一站的服务器会弹回一条 TRACE 响应,并在响应主体中携带它收到的原始请求报文。这样客户端就可以查看在所有中间 http 应用程序组成的请求 / 响应链上原始报文是否、如何被毁坏或修改过。

  TRACE 方法主要用于诊断,即验证请求是否按照期望的那样穿过了请求 / 响应链。

OPTIONS

  OPTIONS 方法请求 web 服务器告知其所支持的各种功能,可以询问服务器通常支持哪些方法,或者对某些资源支持哪些方法

DELETE

  顾名思义,DELETE 方法所做的事情就是让服务器删除 URL 所指定的资源。但是客户端应用程序无法保证删除操作一定会被执行,,因为 http 规范允许服务器在不通知客户端的情况下撤销请求。

扩展方法

  HTTP 被设计成字段可扩展的,这样新的特性就不会使老的软件失效。扩展方法指的就是没有在 HTTP/1.1 规范中定义的方法。服务器会为它所管理的资源实现一些 HTTP 服务,这些方法为开发者提供了一种扩展这些 HTTP 服务能力的手段。

方法 描述
LOCK 允许用户锁定资源——比如可以在编辑某个资源的时候将其锁定
MKCOL 允许用户创建资源
COPY 便于在服务器上复制资源
MOVE 在服务器上移动资源

   并不是所有扩展方法都是在正式规范中定义的,如果你定义了一个扩展方法,很可能大部分 HTTP 应用程序都无法理解。