报文流
Http报文是在Http应用程序之间发送的数据块,这些数据块以一些文本形式的元信息(meta-information)开头,这些信息描述了报文的内容以及含义,后面跟着可选的数据部分。这些报文在客户端、服务器和代理之间流动。术语“流入”(inbound)、“流出”(outbound)、上游以及下游都是用来描述报文方向的。
报文的组成
报文有三部分组成:对报文进行描述的起始行(start line)、包含属性的首部(headers)块,以及可选的、包含数据的主体(body)部分。
- 请求报文
<method> <request-URL> <version> <!--起始行-->
<headers> <!--首部块,首部必须以空行来结束-->
<entity-body> <!--实体-->
- 响应报文
<version> <status> <reason-phrase> <!--起始行-->
<headers> <!--首部块,首部必须以空行来结束-->
<entity-body> <!--实体-->
起始行和首部(可能是0行或者多行)是以行分隔的ASCII文本,每行以CRLF为结束符。
需要注意的是,尽管Http规范中说明应该以CRLF来终止一行,但是一些老的或者不完善的Http程序有可能只会发送一个换行符,因此为了兼容性,最好也接受单个换行符作为行终止符。
首部不管是0个还是多个,都必须以空行作为首部快的结束,但是同样有一些老的或者不完善的程序,在实体为空的情况下,错误地省略了CRLF,因此为了兼容性,Http程序最好也要接受那些没有最后那个CRLF的报文。
起始行
所有的Http报文都以一个起始行作为开始,请求报文起始行说明“要做些什么”,响应报文起始行说明“发生了什么”。
版本号:
版本号会以HTTP/x.y的形式出现在请求和响应报文的起始行中,为HTTP应用程序提供了一种将自己所遵循的协议版本告知对方的方式。
版本号不会被当作小数来处理,而是优先比较x(主版本号),再比较y(次版本号),比如:HTTP/2.22就比HTTP/2.3版本要高,因为22比3大。
方法:
请求行的起始以方法作为开始,方法用来告知服务器要做些什么。Http规范中定义了一组常用的请求方法。
方法 | 描述 | 是否包含主体 |
---|---|---|
GET | 从服务器获取一份文档 | 否 |
HEAD | 只从服务器获取文档的首部 | 否 |
POST | 向服务器发送需要处理的数据 | 是 |
PUT | 将请求的主体部分存储在服务器上 | 是 |
TRACE | 对可能会经过代理服务器传送到服务器上的报文进行追踪 | 否 |
OPTIONS | 决定可以在服务器上执行哪些方法 | 否 |
DELETE | 从服务器上删除一份文档 客户端程序无法保证删除操作一定会被执行,因为Http规范允许服务器在不通知客户端的情况下撤销请求 | 否 |
下面对其中的一些方法进行补充说明:
HEAD
HEAD方法和GET方法的行为很相似,但是服务器在响应中只返回首部,不会返回实体的主体部分。使用HEAD,可以:
- 在不获取资源的情况下了解资源的情况(比如:判断资源的类型)。
- 通过查看响应中的状态码,看看某个对象是否存在。
- 通过查看首部,测试资源是否已经被修改。
服务器开发者必须确保HEAD请求返回的首部与GET请求所返回的首部完全相同。遵循HTTP1/1.1就必须实现HEAD方法。
POST和PUT的区别
POST请求用于向服务器发送数据;PUT用于向服务器的资源(比如文件)中存储数据。
安全方法
Http定义了一组安全方法,GET和HEAD都被认为是安全方法,通常来说这就意味着这两种Http请求都不会产生什么动作。但是,这也不是一定的,实际上Web开发者不一定会遵守这种规范。
状态码:
方法是用来告诉服务器做什么事的,状态码则用来告诉客户端发生了什么。可以通过三位数字代码对不同的状态码进行分类:
整体范围 | 已定义范围 | 分类 |
---|---|---|
100 ~ 199 | 100 ~ 101 | 信息提示 |
200 ~ 299 | 200 ~ 206 | 成功 |
300 ~ 399 | 300 ~ 305 | 重定向 |
400 ~ 499 | 400 ~ 415 | 客户端错误 |
500 ~ 599 | 500 ~ 505 | 服务器错误 |
100 ~ 199–信息性状态码
状态码 | 原因短语 | 含义 |
---|---|---|
100 | Continue | 说明收到了请求的初始部分,请客户端继续。发送了这个状态码之后,服务器在收到请求之后必须进行响应。 |
101 | Switching Protocols | 说明服务器正在根据客户端的指定,将协议切换成Update首部所列的协议。 |
对于100 Continue 可能有些人会有些疑惑,这里单独说一下。它的目的是对以下这种情况进行优化:HTTP客户端有一个实体的主体部分要发送给服务器,但是希望在发送之前查看一下服务器是否愿意接收这个实体。
客户端与100 Continue
- 如果客户端想实现上面的优化,可以在http报文中添加一个首部“Except:100-continue”。
- 如果客户端没有实体的主体部分,就不应该发送100 Continue 的 Except 首部,因为这样会让服务器误以为客户端要发送一个实体的主体。
- 客户端应该只有在避免向服务器发送一个难于处理或者大的实体时,才应该使用100 continue。
- 发送了100 Continue Except 首部的客户端不应该永远在那里等待服务器的100 Continue 响应,在超时一定时间之后,客户端要直接将实体发送出去。
- 客户端要做好非预期的100 Continue 响应的处理,因为可能存在之前Http事务的100 Continue 响应,但是客户端已经结束了这次事务。
服务器与100 Continue
- 服务器不应该向没有发送100 Continue 期望的客户端发送100 状态码。
- 如果服务器在发送100 Continue 响应之前,就已经收到客户端发送的实体。那么服务端可以跳过100 Continue状态,直接返回最终的状态码。
- 如果服务器收到了100 Continue 期望的请求,但是决定在接收实体之前结束(比如:服务器出错),这时候不应该仅仅只发送一条响应就直接关闭连接,而是要发送100 状态码和最终状态码。
代理与100 Continue
- 当代理收到一条带有100 Continue Except 首部的客户端请求,如果代理知道下一跳的服务器是HTTP/1.1兼容的,或者不知道其与哪个版本的HTTP协议兼容,那么它都应该直接转发Except 首部。
- 如果代理知道下一跳服务器只能兼容HTTP1.1之前的版本,那么代理应该直接返回417 Exceptation Failed。
- 如果代理私自添加了100 Continue Except 首部,那么在将响应转发给客户端的时候,应该忽略100 Continue,因为客户端可能不知道要拿它怎么办。
其他常用的状态码
这里只列出了一些常用的已定义状态码,更加完整的状态码信息,可以查看维基百科。
状态码 | 原因短语 | 含义 |
---|---|---|
200 | OK | 请求成功,实体的主体部分包含了所请求的资源。 |
201 | Created | 用于创建服务器对象的请求(比如:PUT)。响应的实体的主体部分应该包含各种引用了已创建资源的URL,Location 首部包含的则是最具体的引用。 |
202 | Accepted | 请求已经被接受,但是服务器还没有对其执行任何动作。 |
301 | Moved Permanently | 永久重定向,在请求的 URL 已经被移除的时候使用,响应的 Location 首部中应该包含资源现在所处的 URL。 |
302 | Found | 临时重定向,与301状态码相似,客户端应该使用 Location 首部给出的 URL 来临时定位资源,将来还是使用老的 URL。 |
303 | See Other | 告知客户端应该用另外一个 URL 来获取资源。新的 URL 由 Locatiion 首部给出。其主要的目的是允许 POST 请求的响应将客户端定向到某个资源上去(比如:修改物品信息后,直接跳到该物品信息展示页面)。 |
307 | Temporary Redirect | 和302功能一样,但是这是Http/1.1使用,302是Http/1.0使用。 |
400 | Bad Request | 客户端发送了错误的请求。 |
401 | Unauthorized | 权限认证失败。 |
403 | Forbidden | 请求被服务器拒绝,服务器可以在实体描述为什么拒绝请求,但是这个状态码一般是在服务器不想说明拒接原因的情况下使用的。 |
404 | Not Found | 服务器无法找到请求的资源 |
500 | Internal | 服务器可以处理客户端的请求,但是处理时发生了错误。 |
503 | Not Implemented | 服务器无法处理客户端的请求。 |
原因短语:
原因短语是响应起始行的最后一个组件,它与状态码是成对出现的。原因短语是状态码的可读版本,用于说明请求期间发生了什么。不过Http并没有硬性规定,要求原因短语是以何种形式出现,但是有一些官方建议使用的短语。
首部
在请求和响应报文中都可以使用首部来提供信息,有些首部是某种报文专用的,有些首部则更加通用一些,可以将首部分为五个主要的类型。
通用首部
请求报文和响应报文都可以使用的首部。
通用信息性首部
首部 | 描述 |
---|---|
Connection | 允许客户端和服务器指定与请求/响应连接有关的选项 |
Date | 提供日期和时间标记,说明报文是什么时候创建的。 |
MIME-Version | 给出了发送端使用的MIME版本。 |
Trailer | 如果报文采用 分块传输编码(chunked transfer encoding)方式,就可以用这个首部列出位于报文拖挂(trailer)部分的首部集合。 |
Transfer-Encodeing | 告知接收端为了报文的可靠传输,对报文使用什么样的编码格式。 |
Update | 给出了发送端可能想要“升级”使用的新版本或协议 |
Via | 显示了报文经过的中间节点(代理、网关),比如:使用TRANCE请求的时候,就有可能看到这个首部。 |
通用缓存首部
首部 | 描述 |
---|---|
Cache-Control | 用于随报文传送缓存指示。 |
Pragma | 另一种随报文传送指示的方式,但是并不是专用于缓存。 |
请求首部
请求的信息性首部
首部 | 描述 |
---|---|
Client-IP | 客户端的机器的Ip地址。 |
From | 客户端用户的Email。 |
Host | 目标服务器的主机名和端口号。 |
Referer | 提供了当前请求 URI 的文档的 URL。 |
UA-Color | 客户端显示器颜色有关的相关信息。 |
UA-CPU | 客户端CPU类型或制造商。 |
UA-Disp | 提供了客户端显示器能力有关的信息。 |
UA-OS | 客户端机器上的操作系统名称以及版本。 |
UA-Pixels | 客户端显示器的像素信息。 |
User-Agent | 发起请求的应用程序名称。 |
Accept首部
首部 | 描述 |
---|---|
Accept | 告诉服务器当前客户端能够接收哪些媒体类型。 |
Accept-Charset | 告诉服务器当前客户端能够接收哪些字符集 |
Accept-Encoding | 告诉服务器当前客户端能够接收哪些编码方式 |
Accept-Language | 告诉服务器当前客户端能够接收哪些语言。 |
TE | 告诉服务器当前客户端可以接收哪些扩展传输编码息。 |
条件请求首部
首部 | 描述 |
---|---|
Except | 列出某请求所要求的服务器行为。(比如:100-continue) |
If-Match | 如果实体标记和当前文档的实体标记向匹配,则获取当前这份文档。 |
If-None-Match | 如果实体标记和当前文档的实体标记不匹配,则获取当前这份文档。 |
If-Modified-Since | 除非在某个指定的日期之后资源被修改过,否则就限制这个请求。 |
If-Unmodified-Since | 除非在某个指定的日期之后资源没被修改过,否则就限制这个请求。 |
If-Range | 允许对文档的某个范围进行条件请求。 |
Range | 指定范围请求的范围。 |
安全请求首部
首部 | 描述 |
---|---|
Authorization | 提供认证信息 |
Cookie | 客户端向服务器传递一个令牌。 |
Cookie2 | 用来说明请求端支持的Cookie版本。 |
代理请求首部
首部 | 描述 |
---|---|
Max-Forward | 请求发送到目标服务器,中间可以跳转的最大次数-与TRACE方法一起使用。 |
Proxy-Authorization | 携带代理认证信息 |
Proxy-Connection | 与 Connection 首部相同,但是这个首部是与代理建立连接的时候使用的。 |
响应首部
响应的信息性首部
首部 | 描述 |
---|---|
Age | (从最初创建开始)响应的持续时间。(暗示响应可能是从中间节点,很可能是从代理的缓存传送过来的) |
Public | 服务器为其资源支持的请求方法列表。 |
Retry-After | 如果资源不可用,在此日期或者时间重试。 |
Server | 服务器应用程序的软件名称或者版本。 |
Title | Html文档标题。 |
Warning | 比原因短语中更详细一些的警告报文。 |
协商首部
首部 | 描述 |
---|---|
Accept-Ranges | 对此资源来说,服务器可以接受的范围类型。 |
Vary | 一个首部列表,服务器会根据这些首部的内容挑选出最合适的资源版本发送给客户端。 |
安全响应首部
首部 | 描述 |
---|---|
Proxy-Authenticate | 来自代理服务器的质询列表 |
Set-Cookie | 为客户端设置一个令牌,以便服务器对客户端进行标识。 |
Set-Cookie2 | 与 Set-Cookie 相似,RFC 2965 Cookie 定义。 |
WWW-Authenticate | 来自服务器的质询列表 |
实体首部
实体的信息性首部
首部 | 描述 |
---|---|
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程序也要接受它们并且对其进行转发。
参考资料
《Http权威指南》