HTTP报文概览
本文主要对报文的流动及其内容的理解做了介绍。包括以下内容:
报文的流动
报文的组成部分(起始行、首部和实体的主体部分)
报文的区别(响应报文和请求报文之间)
方法介绍
状态码介绍
HTTP首部作用
这里要强调的是,这个最多是我抄书的理解,并不全面。请大家看的时候还需要用慧眼进行鉴别。
一、报文的流动
HTTP报文是指在HTTP应用程序之间收发的数据块。其以文本形式的元信息开头,描述报文的内容和含义,而后接续可选部分。这里有三个术语:
流入(inbound)
流出(outbound)
事务处理(transaction)
流入是指从客户端到服务器的事务处理方向;而流出则是从服务器到客户端的事务处理方向。但不管是哪种流动,所有报文都向下(downstream)流动,而报文的发送者都在接受者的上游(upstream)。注意,这里的上游和下游都只和发送者、接受者有关,而服务器和客户端都是下游节点,所以我们无法区别报文的发送方向。
二、报文的组成部分
HTTP报文分请求报文和响应报文两种,它们都由三个部分组成:
起始行:对报文进行描述。
首部:包含属性
主体:可选的,包含数据。
起始行和首部是由行分隔的ASCII文本,都包括了一个回车符和一个换行符,可写作CRLF。但是,由于部分HTTP应用程序不总是发送CRLF,所以一个HTTP应用程序应该接受单个换行符作为终止。主体可以包含文本或者二进制数据,也可以为空。
1.语法
HTTP报文分为两类,而语法不同。请求报文的格式为:
<method> <request-URL> <version>
<headers>
<entity-body>
而响应报文在格式上,只有起始行有别:
<version> <status> <reason-phrase>
接下来将对其中的大部分内容进行详细介绍,而实体则在日后详谈。这里简述下实体<entity-body>
:包含一个由任意数据组成的数据块,是可选的。
2.起始行
起始行分为请求行和响应行。
2.1.请求行
请求报文的起始行,包含一个方法和一个请求URL。方法描述需要执行的操作,而请求URL则描述操作对象。请求行还包含客户端的HTTP协议版本。这些字段使用空格符" "分隔。注意,在HTTP/0.9不要求请求中包含HTTP版本号。
2.2.响应行
响应报文的起始行,包含响应报文使用的HTTP协议版本、数字状态码和原因短语。所有字段使用空格符" "分隔。
2.3.方法
告知服务器要进行的操作。HTTP规范中描述了一组方法,而在HTTP规范之外的方法,则是扩展方法,是HTTP规范的拓展。常用HTTP方法有:
方法 | 描述 | 是否包含主体 |
---|---|---|
GET | 从服务器中获取文档 | 否 |
HEAD | 从服务器获取文档首部 | 否 |
POST | 向服务器发送需要处理的数据 | 是 |
PUT | 将请求的主体存储在服务器上 | 是 |
TRACE | 对可能经过代理服务传送到服务器上的报文进行追踪 | 否 |
OPTIONS | 查询服务器支持的方法 | 否 |
DELETE | 从服务器上删除文档 | 否 |
2.4.状态码
服务器对客户端操作结果的回应。状态码有五种分类,而当前HTTP版本只规定了其中一部分。如果接收到拓展的状态码,则会按照其所属范围进行分类,而后按照该分类中的普通成员处理。状态码分类如下:
整体范围 | 已定义范围 | 分类 |
---|---|---|
100~199 | 100、101 | 信息提示 |
200~299 | 200~206 | 成功 |
300~399 | 300~305 | 重定向 |
400~499 | 400~415 | 客户端错误 |
500~599 | 500~505 | 服务器错误 |
后面会解释当前使用的所有状态码,这里按下不表。
2.5.原因短语
与状态码同时出现,是其文本形式,但是HTTP规范对此并没有任何规定,但是有推荐的文本内容。
2.6.版本号
以HTTPx.y出现,使得HTTP客户端和服务器可以了解双方的能力和报文。注意,其版本号不会被当作小数处理,每一个数字都会单独比较。
3.首部
其作用是向报文添加附加信息,本质上是名/值对的列表,用冒号":"分开名与值,可以分为五种:通用首部、请求首部、响应首部、实体首部和扩展首部。首部的语法如下:<headers>: (可选的空格)<value>\r\n
首部可以有多行,为了增强可读性,从第二行开始要在前面加一个空格或者制表符。
4.实体的主体部分
是HTTP报文的符合,即其要传输的内容。HTTP报文可以承载多种类型的数字数据,包括HTML文档、图片、视频等。
5.HTTP0.9的报文
这是HTTP协议早期版本,由请求和响应构成,但是请求中只包含方法和请求URL,而响应中只包含实体。由于其却放灵活性,不能使用大部分提到的方法,但是在部分应用上仍旧使用,开发者应该清楚其局限。
三、方法
这部分是对前面的基本方法的深入探讨。有以下几点要注意:
并不是每个服务器实现了所有方法
服务器中部分方法的使用可能是受限的,而限制则在服务器的配置中进行设置。
1.安全方法
这是由HTTP协议定义的,其中包括GET和HEAD方法。安全方法意味着不产生动作,但这由Web开发者决定。相对应的,使用不安全的方法时,会允许HTTP应用开发者通知用户,这才是目的。
2.GET方法
常用方法,用于请求服务器发送某个资源,在HTTP/1.1中,要求服务器实现该方法。
3.HEAD方法
类似GET方法,但是响应只返回首部。目的是允许客户端对资源的首部进行检查。该方法有以下作用:
不获取资源的前提下了解资源情况
查看对象是否存在
测试资源是否被修改
规范要求其返回的首部于GET方法获得的相同。
4.PUT方法
向服务器写入文档,其方法的语义即让服务器用请求的主体部分(body)创建或者覆盖所请求的URL命名的新文档。由于其允许用户修改文件,通常要求进行密码认证。该方法需要存储资源。
5.POST方法
起初用来输入数据,现多用来支持HTTP表单。表单体拿到的数据发送给服务器,再由服务器决定去向。该方法不需要存储资源。
6.TRACE方法
在客户端发起请求以后,当它穿过其他应用程序的中间节点时可能被修改。而TRACE方法允许客户端最后将请求发送给服务器。
该请求会进行“环回”诊断,即在服务器弹回一条携带收到的报文的TRACE响应,使得客户端能查看原始报文的修改情况。TRACE方法用于诊断,验证请求是否穿过了请求/响应链,但由于其假设中间应用程序对各种不同类型的请求的处理相同,所以其不能区别HTTP程序对不同方法的处理机制的差异。
TRACE请求中不能带有实体的主体部分。响应主体则包含收到的请求主体的精确副本。
7.OPTIONS方法
请求Web服务器告知其支持的所有方法,这些方法是通用于服务器上所有资源的。这使得客户端可以判定请求资源的最优方法。(就是优化)
8.DELETE方法
请求服务器删除请求URL指定的资源,但是客户端程序不保证删除操作被执行。
9.拓展方法
由于HTTP被设计为字段可拓展的,新旧特性可以兼容。而拓展方法指的是:没有在HTTP/1.1规范中定义的方法。常见拓展方法实例如下:
方法 | 描述 |
---|---|
LOCK | 允许用户“锁定”资源,以防编辑时被其他人修改。 |
MKCOL | 允许用户创建资源 |
COPY | 复制服务器上的资源 |
MOVE | 移动服务器的资源 |
上面的拓展方法是在WebDAV HTTP拓展中定义的拓展方法。要注意的是,并非所有拓展方法都可以被理解或者应用,所以,最好对拓展方法宽容以待,只要不破坏端到端行为,可以传递给下游服务器;如果可能破坏,则传递501 Not Implemented进行响应。惯例是:“对发送的内容要求严格,对接受的内容要求宽松”。
四、状态码
目的是便利客户端理解事务处理的结果,分为五大类,而五大类中的每个状态码都有一个HTTP/1.1推荐使用的原因短语。
1.信息性状态码100~199
在HTTP/1.1中引入,存在争论,受到限制。其主要内容如下:
状态码 | 原因短语 | 含义 |
---|---|---|
100 | Continue | 说明收到请求的初始部分,请客户端继续。发送了这个状态码以后,服务器在收到请求之后必须响应。 |
101 | Switching Protocol | 说明服务器正在根据客户端的指定,将协议切换成Update首部所列的协议 |
在这里,要对100状态码进行一个解释。其针对的情境是:客户端需要发送一个实体给服务器,但要在发送之前检查一下服务器是否会接受该实体。而它在客户端、服务器和代理之间是这样通信的:
客户端与100状态码
客户端可以发送一个携带了值为100Continue的Expect请求首部,从而可以在发送实体之前等待100Continue的响应。这用于避免向服务器发送一个无法处理的大实体。注意,如果等待超时,则客户端应该直接发送实体;要应对非预期的响应。
服务器与100状态码
服务器在收到带有值为100Continue的Expect首部的请求时,应该用100Continue或者其他错误状态码进行响应。但是,如果客户端没有要求,则服务器不应该发送该响应。
如果服务器在发送100Continue之前就收到部分实体,即客户端已经超时了,服务器就不需要发送100状态码,但是读完请求以后,应该发送一个最终状态码(可跳过100状态码)。
代理与100状态码
代理收到一个100Continue的Expect请求,则能做的分以下几种情况:
知道下一跳服务器是HTTP/1.1兼容(或者不知道),则将Except首部向下转发
知道下一跳服务器只与HTTP/1.1之前兼容,则应该响应417Exception Failed错误(或者是先向客户端返回100Continue,而后在向服务器转发请求的时候,删除Except首部)。
代理代表与HTTP/1.0或之前的版本兼容的客户端,则可以向请求中放入Except首部与100Continue值,但是不能向客户端转发该状态码。
所以,代理维护下一跳服务器及其版本信息有优点:更好地处理100Continue期望的请求。
2.成功状态码200~299
成功的请求有不同类型,所以下面有不同的表示成功的状态码。
状态码 | 原因短语 | 含义 |
---|---|---|
200 | OK | 请求没问题,实体的主体部分包含请求的资源。 |
201 | Created | 对用于创建服务器对象的请求的响应。其实体的主体部分应该包含各种引用了已创建资源的URL,Location首部包含的是最具体的引用。 |
202 | Accepeted | 请求已被接受,但是未执行并不保证执行请求。服务器应该在实体的主体部分包含对请求状态的描述,以及完成请求的时间的估算(或者可以获得此信息位置的指针)。 |
203 | Non-authoritative Information | 实体首部包含的信息来自资源的副本(而非服务器)。在中间节点有资源副本,但是无法或者没有对它发送的与资源有关的首部进行验证时,出现的情况。 |
204 | Not Content | 响应报文包含首部和状态行,但是没有实体的主体部分。用于在浏览器不转为显示新文档的情况下,对其进行更新。 |
205 | Reset Content | 用于浏览器,告知浏览器清楚当前页面中所有HTML表单元素。 |
206 | Partial Content | 成功执行一个部分或者Range请求。其必须包含Content-Range\Date或者Content-Location首部。 |
3.重定向状态码300~399
告知用户使用替代位置来访问资源,或者提供一个替代的响应而不是资源内容。如果资源已移动,则可以发送重定向状态码以及一个可选的Location首部来告知客户端资源已被移动,以及当前位置。这样浏览器可以透明转入新的位置。
也可以通过重定向状态码验证本地资源与服务器资源,用于查看服务器资源的修改,以及保持本地副本的及时性。
对包含了重定向状态码的非HEAD请求进行响应,则包含一个实体,并在实体中描述信息和指向(多个)重定向URL的连接。
状态码 | 原因短语 | 含义 |
---|---|---|
300 | Multiple Choices | 客户端请求一个实际上指向多个资源的URL时返回。服务器在返回时,可以在Location首部包含首选URL |
301 | Moved Permanently | 在请求的URL已经移除时使用。响应的Location首部则包含资源的现URL |
302 | Found | 类似301,但是Location首部给出的URL只能临时定位资源,之后的请求应使用旧URL |
303 | See Other | 告知客户端应使用另一个URL获取资源。新URL位于Location首部,目的是允许POST请求的响应将客户端重定向到某个资源上 |
304 | Not Modified | 客户端可以通过包含的请求首部,使其变为有条件的。条件首部的内容可以在后面看到。带有该状态码的响应不包含实体的主体部分。 |
305 | Use Proxy | 说明该资源必须通过代理访问。代理位置由Location首部指出。客户端是相对某个特定资源解析该响应,而不是指定所有资源通过该代理进行。 |
307 | Temporary Redirect | 类似301。但是Location首部给出的URL只能临时定位资源,之后的请求应使用旧URL |
状态码302、303、307之间存在交叉和细微的差别,而其源于HTTP/1.0和HTTP/1.1应用程序之间的差别。
对于HTTP/1.0客户端,发起POST请求并收到302响应时,会接受Location首部的重定向URL,并发送GET请求。
对HTTP/1.0服务器,要求客户端像上面一样做。
但是HTTP/1.1使用303状态码实现相同行为,所以,对于HTTP/1.1客户端,使用307状态码来代理302状态码,以避免302状态码被覆盖。
4.客户端错误状态码400~499
服务器收到无法处理的内容时的响应。
状态码 | 原因短语 | 含义 |
---|---|---|
401 | Bad Request | 告知客户端发送了一个错误请求。 |
402 | Unauthorized | 与适当的首部一同返回,请求客户端在获取资源的访问权以前,对自己进行认证。 |
403 | Payment Required | 未使用,但是保留到未来使用。 |
404 | Not Found | 服务器无法找到请求的URl,通常包含一个实体,显示给客户端。 |
405 | Method Not Allowed | 发送的请求中带有URl不支持的方法。其在响应中应该包含Allow首部,告知该资源可以使用的方法。 |
406 | Not Acceptable | 在没有客户端可接受的URL相匹配的资源时使用,客户端可以指定参数来说明它们愿意接受的实体类型。 |
407 | Proxy Authentication Required | 类似401,但是用于对要求对资源进行认证的代理服务器。 |
408 | Request Timeout | 客户端完成请求的时间超时,服务器发送此状态码并关闭连接。 |
409 | Conflict | 说明请求可能在资源上引发的冲突。在服务器担心请求可能会引发冲突时,发送此状态码。响应中应包含描述冲突的主体。 |
410 | Gone | 类似404,只是服务器曾经拥有该资源,用于站点的维护,可以在服务器的资源被移除时通知客户端。 |
411 | Length Required | 服务器的要求 |
412 | Precondition Failed | 发起条件请求,但是其中一个条件失败时使用。 |
413 | Request Entity Too Large | 客户端发送的实体主体部分大于服务器能处理的内容。 |
414 | Request URI Too Long | URL实在太长。 |
415 | Unsupported Media Type | 服务器无法理解或者无法支持客户端所发送的实体的内容类型时使用。 |
416 | Requested Range Not Satisfiable | 请求报文请求的是指定资源的某个范围,但是该范围无效或者无法满足。 |
417 | Expectation Failed | 包含期望的请求无法由服务器满足。如果代理或者中间程序有确切证据说明服务器必然会产生一个失败的期望,则可以发送这个响应状态码。 |
有一个403Forbidden,好像是服务器拒绝处理请求,并且不说明原因。
5.服务器错误状态码500~599
客户端的请求有效,但是服务器出错时,可以使用,这是通常是代理与服务器交流的结果。
状态码 | 原因短语 | 含义 |
---|---|---|
500 | Internal Server Error | 服务器遇到一个妨碍它为请求提供服务的时候使用。 |
501 | Not Implemented | 客户端发起的请求超过服务器能力时使用 |
502 | Bad Gateway | 作为代理或者网关使用的服务器从请求响应链的下一条链路上收到了一条伪响应时使用 |
503 | Sevice Unavailable | 用来说明服务器现在无法为请求提供服务,但是将来可以啊(有种备胎的感觉) |
504 | Gateway Timeout | 类似408,但是该响应来自一个网关或者代理 |
505 | HTTP Version Not Supported | 收到的请求的版本不符。 |
五、首部
首部与方法配合使用,决定服务器和客户端的动作。其有五种首部,在下面进行详细论述。
1.通用首部
提供与报文相关的最基本的信息,可以由两种报文使用。信息性首部有:
首部 | 描述 |
---|---|
Connection | 允许客户端和服务器指定与请求/响应连接相关的选项 |
Date | 提供日期和时间标志,说明报文创建的时间 |
MIME-Version | 给出发送端使用的MIME版本 |
Trailer | 报文采用了分块传输编码时,使用该首部列出位于报文拖挂(trailer)部分的首部集合。 |
Transfer-Encoding | 告知报文采用的编码方式 |
Update | 给出发送端可能想要“升级”使用的新版本或者协议 |
Via | 显示报文经过的中间节点 |
而通用缓存首部则是在HTTP/1.0中引入的,允许HTTP应用程序缓存本地副本的首部,而不用直接从服务器中获取。基本的缓存首部如下:
首部 | 描述 |
---|---|
Cache-Control | 用于随报文传送缓存指令 |
Pragma | 另一种随报文传送指令的方式,但是非专门用于缓存 |
2.请求首部
在请求报文中特有的内容。对服务器提供更详细的有关客户端的信息。其信息性首部有:
首部 | 描述 |
---|---|
Client-IP | 运行客户端的机器的IP |
From | 客户端用户的邮箱地址 |
Host | 请求的服务器主机名和端口号 |
Referer | 包含当前请求URL的文档的URL |
UA-Color | 提供了与客户端显示器对颜色的支持的有关信息 |
UA-CPU | 提供了客户端的CPU类型或制造商 |
UA-Disp | 提供客户端显示器能力相关信息 |
UA-OS | 提供客户端操作系统信息——名称及其版本 |
UA-Pixels | 提供客户端显示器像素 |
User-Agent | 将发起请求的应用程序名告知服务器 |
2.1.Accept首部
为客户端提供将器喜好和能力告知服务器的方式,从而使得连接的两端都得益。主要的Accept首部如下:
首部 | 描述 |
---|---|
Accept | 告诉服务器能够发送那些媒体类型 |
Accept-Charset | ...能够发送的字符集 |
Accept-Encoding | ...能够接受的编码方式 |
Accept-Language | ...能够发送的语言 |
TE | 能使用那些扩展传输编码 |
2.2.条件请求首部
为请求加上限制,要求服务器在响应之前,确保条件为真。
首部 | 描述 |
---|---|
Expect | 允许客户端列出某请求所要求的服务器行为 |
If-Match | 如果实体标记与文档当前的实体标记匹配,则获取文档 |
If-Modfied-Since | 除非在指定日期之后资源被修改,否则限制该请求 |
If-None-match | 如果实体标记与文档当前的实体标记不匹配,则获取文档 |
If-Range | 允许对文档的某个范围进行条件请求 |
If-Unmodified-Since | 除非在指定日期之后资源没被修改,否则限制该请求 |
Range | 如果服务器支持范围请求,请求资源的指定范围 |
2.3.安全请求首部
对请求进行质询后者响应认证。要求客户端在获取特定资源之前,对自身进行认证,从而提高事务安全性。
首部 | 描述 |
---|---|
Authorization | 包含客户端提供给服务器,以便对其自身进行认证的数据 |
Cookie | 传递给服务器的一个令牌,隐含安全功能 |
Cookie2 | 用来说明请求端支持的Cookie版本 |
2.4.代理请求首部
由于代理的普遍应用而来。
首部 | 描述 |
---|---|
Max-Forward | 在通往源服务器的路径上,将请求转发给其他代理(网关)的最大次数,与TRACE一同使用 |
Proxy-Authorization | 与同名首部功能相同,但是用于代理 |
Proxy-Connection | 与同名首部功能相同,但是用于代理 |
3.响应首部
由响应报文使用,为客户端提供额外的信息,包括信息性首部、协商首部和安全响应首部。信息性首部如下:
首部 | 描述 |
---|---|
Age | 响应持续时间 |
Public | 服务器为资源提供的方法列表 |
Retry-After | 资源不可用则在该日期或者时间重试 |
Server | 服务器应用的名称和版本 |
Title | HTML源端给定的标题 |
Warning | 比原因短语详细的警告报文 |
而协商首部则是用来传递与可协商资源有关的信息。
首部 | 描述 |
---|---|
Accept-Range | 对该资源来说,服务器可以接受的范围类型 |
Vary | 服务器查看的其他首部的列表,可能使响应变化。即由服务器决定最适合的资源版本发送给客户端 |
安全响应首部则是HTTP的质询/响应认证机制的响应侧。安全响应首部如下:
首部 | 描述 |
---|---|
Procy-Authenticate | 来自代理对客户端的质询列表 |
Set-Cookie | 在客户端设置令牌,标识客户端 |
Set-Cookie2 | 类似上面 |
WWW-Authenticate | 来自服务器的对客户端的质询列表 |
4.实体首部
可以出现在两种报文中,提供有关实体及其内容的大量信息,其信息性首部有:
首部 | 描述 |
---|---|
Allow | 列出对该实体可以执行的请求方法 |
Location | 告知客户端实体的位置,用于定向到资源的位置 |
内容首部包含的是与实体内容有关的特定信息。
首部 | 描述 |
---|---|
Content-Base | 解析主体中相对URL时使用的基础URL |
Content-Encoding | 对主体执行的编码方式 |
Content-Language | 理解主体适合的自然语言 |
Content-Length | 长度 |
Content-Location | 位置 |
Content-MD5 | MD5校验码 |
Content-Range | 该实体表示的字节范围 |
Content-Type | 对象类型 |
缓存首部则说明了被缓存的主体的信息。
首部 | 描述 |
---|---|
ETag | 与实体相关的实体标记 |
Expires | 实体不再有效,要从原始的源端中再次获取该实体的日期和时间 |
Last-Modified | 实体最后一次被修改的日期和时间 |
这里就是本章的全部内容,虽然有一些图有所缺漏,但是至少看懂HTTP报文大概是怎么回事应该没问题了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。