Message of HTTP

HTTP(HyperText Transfer Protocol) is a stateless(无状态) application-level request/response protocol that uses extensible semantics(可扩展语义) and self-descriptive(自描述) message payloads for flexible interaction with network-based hypertext information systems. - from RTC7230

HTTP是一种能够获取HTML这样的网络资源的通讯协议。是web上进行数据交换的基础,是一种client-server协议。

HTTP是应用层的协议,通过TCP或者TLS(加密的TCP)连接来发送信息,不仅用来传输超文本文档,也可以传输图片、视频,也可以部分文档内容更新网页。

996年,HTTP的下一个版本,即HTTP/1.0的演变比原始版本有了很大的改进。

与仅为HTML响应设计的HTTP/0.9不同,HTTP/1.0现在可以处理其他响应格式,即图像、视频文件、纯文本或任何其他内容类型。它添加了更多方法(即POST和HEAD),更改了请求/响应格式,将HTTP标头添加到请求和响应中,添加了状态代码以识别响应,引入了字符集支持,包括多部分类型、授权、缓存、内容编码等。

以下是示例HTTP/1.0请求和响应的样子:

GET / HTTP/1.0
Host: cs.fyi
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*

如您所见,除了请求外,客户还发送了其个人信息、所需的响应类型等。虽然在HTTP/0.9中,客户端永远无法发送此类信息,因为没有headers。

对上述请求的示例响应可能如下所示

报文

报文主要是在客户端服务端之间进行流通。Client发送的报文称为请求报文,服务端返回给Client的称之为响应报文。

报文是数据传输的载体,互联网上所有展示的信息以及服务器流通的数据都是报文。

报文组成

Client发送一个HTTP请求向服务端,这个请求以一个请求行(request-line)开始,包含了Method、Path、Protocol Version;接下来是请求修饰符(request modifiers),包含了客户端信息以及表示元数据的头字段;最后就是包含有效负载的消息正文。

报文语法

HTTP-message = start-line
*(header-field CRLF)
CRLF
[ message-body ]

起始行以及头部

起始行(start-line)包含了请求行(request-line)和响应行(status-line)。

起始行包含了客户端请求的一些方法

请求方法

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

响应行也就是服务端反馈给客户端状态信息,也就是状态码以及响应短语。

首部

Header Field 包含了一个不区分大小写Field Name后面跟 ":" 以及 Field Value。

所有的消息头都在IANA注册表中列出,原始内容在 RFC4229 定义。

Header-field = field-name ":" OWS field-value OWS
OWS = Optional whiteSpace

首部和方法共同决定了客户端和服务器要做什么。首部主要分为四个类型。

  • 通用首部
  • 请求首部
  • 响应首部
  • 实体首部

通用首部

通用首部是客户端和服务器都可以使用的,提供了与报文相关的基础功能。在客户端和服务器都提供一些通用的功能,比如 **Date,每一端都可以用它来构建报文的时间。**通用首部只能在请求头部或者响应头部,不能在实体头部。

headerdescription
Connection允许客户端和服务器指定请求或者响应是否连接选项
Date报文创建的时间
Cache-Control随报文传递是否缓存指示
Transfer-Encoding告知接收端为了传输安全,报文采用什么编码方式
Trailer实现报文主体后记录哪些首部字段,该首部字段可以使用在HTTP/1.1版本分块传输编码时。 Trailer: Expiress
Upgrade要求服务器升级到一个高版本协议
Via告诉服务器,这个请求是哪些代理发出去的

Connection

Connection header 决定当前事务(请求/响应)结束后,是否关闭网络连接。如果其值是Keep-alive,网络连接就是持久性的。这样同一个服务器上的请求都可以在这个连接上完成。

Connection: keep-alive // 持久连接 http/1.1 的默认值
Connection: close // 关闭网络连接 http/1.0 的默认值

Date

Date 包含了报文创建的时间和日期

Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
// GMT 格林尼治时间 不是本地时间
// Date: Wed, 21 Oct 2020 08:29:33

Cache-Control

Cache-Control 被用于请求和响应中,通过指定来实现缓存机制。缓存是单向的,请求中设置了,只在请求中有效。

缓存指令

// 客户端缓存指令
Cache-Control: max-age=<second> // 设置缓存的最大周期,单位S
Cache-Control: max-stale[=<second>] // 客户端可以接受过期的资源
Cache-Control: no-cache // 发布缓存副本之前,强制要求把请求交给原始服务器进行验证(协商缓存)
Cache-Control: no-store // 不使用任何缓存,缓存不应该存储有关客户端或者服务器响应的任何内容
Cache-Control: no-transform // 不得对资源进行转换或者转变
// 服务器缓存指令
Cache-Control: public // 响应可以被任何对象缓存
Cache-Control: private // 响应只能被单个用户缓存

有关Cache-Control的其他指令,可以查询[RFC7234] 或者 [MDN Cache-Control]

Transfer-Encoding

Transfer-Encoding 指明将消息实体传递给用户所采用的的编码方式。一般出现在响应头部。仅用于两个节点之间消息传输,如果是端到端之间的传输,采用Content-Encoding

Transfer-Encoding: chunked // 数据以分块的方式发送
Transfer-Encoding: compress // 采用Lempel-Ziv-Weich压缩算法
Transfer-Encoding: gzip // 采用Lempel-Ziv coding 压缩算法
// e.g
Transfer-Encoding: gzip, chunked

有关Transfer-Encoding 其他的描述以及指令,可以查询[RFC7230] 或者 [MDN Transfer-Encoding]

请求首部

请求首部主要是针对请求报文中有意义的首部。服务器可以根据客户端请求报文中提供的首部进行更好的响应。

请求首部根据不同功能也分为以下类型

信息型首部

信息型首部主要是提供的当前请求报文的载体(客户端)的信息

Headerdescription
Client-IP客户端机器的IP地址
From提供了客户端中用户的E-Mail地址
Host提供了请求服务器的主机地址以及端口号(无 默认 HTTPS 443 HTTP 80)
Referer包含了当前请求URL的来源页面的地址
User-Agent将发起请求的客户端的名称告知服务器 用户代理

Referer 首部

此请求头表示了该页面是从来源页面的链接进入的,因此,使用Referer头可以记录到用户浏览信息,可以用来统计分析、日志分析以及缓存优化等。

下面两种情况 referer 是不会发送的

  • 来源页面采用的协议表示本地的 “file” 或者 “data" URL
  • 当前请求页面采用的是HTTP,来源页面采用的是安全协议

Accept 类型首部

Accept header 主要是告知服务器 客户端可以处理什么类型的内容。内容类型用MIME类型(媒体类型)表示。服务器在响应头 Content-type 应答客户端。

HeaderDescription
Accept告知服务器可以接受的媒体类型
Accept-Charset告知服务器可以处理的字符集
Accept-Encoding告知服务器能够发送哪些编码
Accept-Language告知服务器能够发送哪些语言

客户端为请求加上某些限制时,使用条件型首部。

HeaderDescription
Expect允许客户端列出某请求的所要求的服务器行为
If-Match实体标记和文档当前的实体标记相匹配,获取文档
If-None-Match实体标记和文档当前的实体标记不相匹配,获取文档
If-Modified-Since某个资源在指定日期之后修改过,则返回对应资源
If-Unmodified-Since某个资源在指定日期之后没有修改过,则返回对应资源
If-Range允许对文档的某个范围内进行请求

安全型首部

在客户端获取特定的响应资源时,会先对自身进行验证。这个也叫HTTP一种安全机制 质询/响应认证

HeaderDescription
Authorization客户端提供给服务端的自身数据进行验证
Cookie客户端向服务器提供一个令牌

Cookie Header

代理型首部

代理型的首部目前有 Proxy-AuthenticateProxy-Authentication-InfoProxy-AuthorizationProxy-FeaturesProxy-Connection

响应首部

响应首部也有其对应的功能,比如谁在发送请求,发送给客户端的信息应该如何处理。

信息型首部

HeaderDescription
Age最初创建开始 响应持续的时间
Server服务器应用程序的软件的名称和版本

协商首部

对资源有多种的表示方法。

协商首部有 Accept-RangesVaryETag,后面对协商首部会有详述。

HeaderDescription
Accept-Ranges是否接收字节范围请求
Vary代理服务器缓存的管理信息
ETag资源的匹配信息

安全首部

安全首部跟请求首部类似

实体首部

实体首部提供了大量跟消息和其内容有关的信息。告知报文的接收者对消息进行什么操作。

信息首部

HeaderDescription
Allow可以对实体执行的请求方法
Location告知客户端实体实际的位置,将接收端定位到定向到资源的URL

内容首部

该首部提供了与实体内容有关的信息

HeaderDescription
Content-Encoding对主体内容执行的编码方式
Content-Language主体内容使用的语言
Content-Length主体内容的长度
Content-Location主体内容的实际位置
Content-MD5主体内容的MD5校验
Content-Range整个资源中该主体内容的表示的字节范围
Content-Type主体的媒体类型

缓存首部

通用的缓存首部说明如何、什么时候缓存。实体首部缓存提供了与被缓存实体有关的信息。

HeaderDescription
ETag与当前实体有关的标记
Expires实体不再有效
Last-Modified当前实体最后一次修改的时间

状态码

  1. [100 - 199]

信息提示 请求已接收,继续进程进程,已定义范围 100 - 101

codereason-phrasedescription
100Continue收到了请求的初始部分,请客户端继续。更多请看[RFC 7231 6.2.1]
101Switching Protocols服务器根据客户端指定,将协议切换成Update首部所列协议更多请看[RFC 7231 6.2.2]
  1. [200 - 299]

成功 请求被成功接收、理解以及处理,已定义范围 200 - 206

codereason-phrasedescription
200OK请求无问题
201Create用户创建服务器对象的请求
202Accepted请求已被接受,但是还没有处理
203Non-Authoritative Information实体首部包含信息不是来源于源服务器
204No Content没有实体主体部分
205Reset Content另一个主要用于浏览器代码
206Partial Content成功执行了一个部分或者range范围请求
  1. [300 - 399]

重定向 需要进一步采取行动 以便完成请求,已定义范围 300 - 305

重定向一般是服务器告知客户端需要进一步去请求资源移动到新服务器。如果资源被移动了,服务器响应重定向状态码以及一个新的资源地址,一边客户端去请求所需资源信息。

重定向还可以识别资源是否被修改过。客户端请求头加了 **If-Modifier-Since,**如果在这个时间之后没有修改文档,则不会返回响应,直接返回状态码。

// 请求报文
POST /test HTTP/1.1
Host: www.nate.com
If-Modifier-Since: Tue Dec 01 2010 16:27:22 GMT
// 响应报文
HTTP/1.1 304 Not Modifier
codereason-phrasedescription
300Multiple Choices客户端请求一个实际指向多个资源的URL会返回
301Move Permanently在请求的URL已被移除时使用
302Found客户端使用Location首部给出的URL来定位资源
303See Other告知客户端使用另一个URL获取资源
304Not Modified告知客户端资源是否被修改过
305Use Proxy必须通过一个代理来访问资源,代理位置由Location给出
  1. [400 - 499]

客户端错误 请求包含错误语法,已定义范围 400 - 415

客户端错误码也是常见的,比如常见的400、404

codereason-phrasedescription
400Bad Request告知客户端发送了一个错误的请求
401Unauthorized由于缺少有效的身份验证,必须传送WWW-Authenticate标头
402Payment Required未使用
403Forbidden请求被服务器拒绝了
404Not Found请求URL未被服务器找到
405Method Not Allowed请求中方法服务器不支持
406Not AcceptTable服务器没有匹配到客户端所要求类型的实体
407Proxy Unauthorized Required用于对资源需要认证的代理服务器
408Request Timeout客户端请求耗时太长
409Conflict在资源上引发一些冲突
410Gone类似404,服务器曾经拥有过资源
411Length Required服务器要求请求报文中包含Content-Length头
412Precondition Failed客户端发起的条件请求,其中一个失败了
413Payload Too Large客户端发起的请求实体主体比服务器所能处理还要大
414Request URL Too Long请求URL太长了
415Unsupported Media Type服务器无法理解请求媒体类型
416Requested Range Not Satisfiable请求报文所请求的是指定资源的范围
417Expectation Failed请求头Except包含了一个期望,服务器无法理解
  1. [500 - 599]

服务器错误,服务器错误执行了请求,已定义范围 500 - 505

codeReason PhraseDescription
500Internal Server Error服务器错误
501Not Implemented客户端发起的请求超出了服务器能力范围
502Bad Gateway作为代理或网关使用的服务器从请求响应链的下一条链路上收到了伪响应
503Service Unavailable服务器无法为请求提供服务
504Gateway Timeout响应来自网关或者代理,等待另一服务器请求超时了
505HTTP Version Not Supported服务器收到的请求使用其无法理解的协议版本

更多有关状态码的信息可以查询 [RFC7231]规范

参考