1 Introduction

https://www.rfc-editor.org/in...

1.1 Purpose

超文本传输协议(HTTP)是一种为分布式,合作式,多媒体信息系统服务的,面向应用层的协议

允许消息以类似MIME的格式传送
相对于HTTP/1.0 功能新增了:分层代理  缓存  持久化连接  虚拟主机

建立在 URI(URL URN)之上
请求方法
请求头
Multipurpose Internet Mail Extensions (MIME)

是一种用户代理(user agent)和网关/代理(proxy)到其他互联网服务器的通用协议。
这些互联网服务器可能由 SMTP [16], NNTP [13], FTP [18], Gopher [2], and WAIS [10] 协议构成

1.3 Terminology 术语

connection
    一种传输层虚拟电路,用于两个程序之间的通信

message
    HTTP 通信基本单元,使用字节序列通过 connection 传输

request
    An HTTP request message
    
response
    An HTTP response message
    
resource
    用 URI 标识网络数据对象和服务,资源可以有多种表示形式(例如多种语言、数据格式、大小和分辨率)
    
entity
    请求头(metainformation 元信息) + 请求体,section 7
    
representation 表示
    特定 response status 有多种表示
    
content negotiation 内容协商
    处理请求选择适当的表现机制。所有响应中实体的表示都是可以协商的(包括错误响应)
    section 12
    
variant 变体
    给定任何时候,一个 resource 可能对应一个或多个 representation,每种 representation 都称为 varriant
    varriant 不代表 resource 受制于 content negotiation
    
client
    为发送请求而建立连接的程序
      
user agent 用户代理
    发起请求的客户端
    
server
    接收连接返回响应的应用程序。每个程序都可以是 origin server, proxy, gateway, or tunnel, 基于他们每个请求的行为。
    
origin server 源服务器
    The server on which a given resource resides or is to be created.
    特定资源创建或所在的服务器

proxy 代理器
    中间服务器,MUST 同时实现 client sever。为请求提供服务或转发(可能会转换)到其他服务器。
    transparent proxy:透明服务器,不修改请求和响应,用户验证和识别除外
    non-transparent proxy:非透明服务器,修改请求和响应。为 user agent 添加一个服务,比如 group annotation services, media type transformation, protocol reduction, or anonymity filtering。
    除非明确声明了透明、非透明,否则 HTTP proxy requirements 同时支持这两种模式
    
gateway 网关
    网关对请求方来说就像源服务器一样

tunnel
    请求的两端关闭,隧道也不复存在

first-head
    响应直接来自 origin server,没经过 proxy。

upstream/downstream 上游 下游
    Upstream and downstream 描述信息流,所有信息都是从上游流向下游。
    此处的信息是指请求+响应码?

inbound/outbound
    inbound:向 origin server 移动
    outbound:向 user agent 移动

1.4 Overall Operation

HTTP protocol 是 request/response 协议. 

客户端通过一条与服务端的连接发送请求,
服务端处理请求后返回响应

请求格式:
request method, URI, protocol version
MIME-like message containing reques modifiers, client information, possible body content

响应格式:
status line:message's protocol version, success or error code
MIME-like message containing server information, entity metainformation, possible entity-body content.

HTTP 与 MIME 的关系位于附录 19.4.

---------------------------- demo 1 ----------------------------

 connection (v)    user agent (UA)    origin server (O).

          request chain ------------------------>
       UA -------------------v------------------- O
          <----------------------- response chain


---------------------------- demo 2 ----------------------------

当 request/response chain 中存在 intermediaries 时,情况会变复杂。
有三种常见 intermediaries:proxy, gateway, and tunnel.
proxy:转发代理,接受绝对形式的 uri 请求,重写 message,重新格式化 request 然后转发
gateway:必要时转换请求的协议。
tunnel:不改写消息,通过 intermediary(例如 firewall),或者 intermediary 无法理解消息时可以使用 tunnel

          request chain -------------------------------------->
       UA -----v----- A -----v----- B -----v----- C -----v----- O
          <------------------------------------- response chain

上图显示了 user agent/origin server 之间的三个中介体(A、B和C),需要四个独立的连接。
这个区别很重要,某些HTTP通信选项分别适用于临近节点,非隧道的临近节点,调用链的终端,任意节点。


---------------------------- demo 3 | 缓存 ----------------------------

          request chain ---------->
       UA -----v----- A -----v----- B - - - - - - C - - - - - - O
          <--------- response chain

    省略关于缓存的一千字 ......

---------------------------- ---------------------------- ----------------------------

HTTP 通信通常使用 TCP/IP connections,默认端口 TCP 80。可以使用任意 Internet 或其他协议。
HTTP 假设传输是可靠的,任意可靠传输的协议都可以使用; HTTP1.1 请求、响应的结构到 transport data units 的映射不在本规范范围内。
HTTP1.1 连接可复用,尽管可能因各种原因关闭(see section 8.1)

2 Notational Conventions and Generic Grammar 符号习惯和一般语法

2.1 Augmented BNF 增强型 Backus-Naur Form

本文规定的所有机制都可以用两种方式描述:散文体(prose)和类似于RFC 822的扩充Backus-Naur Form(BNF)

name = definition
name 代表规则的名称(不能包括 '<' '>' 字符),使用 = 将名称和定义分开,空白是定义的分隔符。
基本规则用大写,例如  SP, LWS, HT, CRLF, DIGIT, ALPHA
'<' '>' 可以包含在定义中,用于标识规则名。

literal(字面量)
文本需加 '', 不区分大小写

rule1 | rule2    rule1 或 rule2
(rule1 rule2)    () 包起来的元素视为单一元素
*rule            重复
    * 表示 0~inf 
    <n>*<m> 表示 n到m次
[rule]            [foo bar] == *1(foo bar)
N rule            <n>(element) == <n>*<n>(element)
#rule            类似于 *,将元素用 (",") 以及 (LWS) 隔开
    1#element == ( *LWS element *( *LWS "," *LWS element ))
    允许出现 (element), , (element)
;                注释
implied *LWS     元素之间需要一个分隔符

2.2 Basic Rules

US-ASCII(美国信息交换标准码)编码字符集是由ANSI X3.4-1986定义

OCTET          = <any 8-bit sequence of data>
CHAR           = <any US-ASCII character (octets 0 - 127)>
UPALPHA        = <any US-ASCII uppercase letter "A".."Z">
LOALPHA        = <any US-ASCII lowercase letter "a".."z">
ALPHA          = UPALPHA | LOALPHA
DIGIT          = <any US-ASCII digit "0".."9">
CTL            = <any US-ASCII control character
                        (octets 0 - 31) and DEL (127)>
CR             = <US-ASCII CR, carriage return (13)>
LF             = <US-ASCII LF, linefeed (10)>
SP             = <US-ASCII SP, space (32)>
HT             = <US-ASCII HT, horizontal-tab (9)>
<">            = <US-ASCII double-quote mark (34)>

CRLF           = CR LF
    HTTP/1.1 将 CR LF 定义为行尾标志
LWS            = [CRLF] 1*( SP | HT )
    与 SP 具有相同的语义
TEXT          = <any OCTET except CTLs, but including LWS>
HEX              = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT
token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | 
                <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
--------------- 注释相关 ---------------
comment        = "(" *( ctext | quoted-pair | comment ) ")"
ctext          = <any TEXT excluding "(" and ")">
quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
qdtext         = <any TEXT except <">>

quoted-pair    = "\" CHAR

3 Protocol Parameters 协议参数

3.1 HTTP Version

格式 <major>.<minor>
HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
HTTP/1.0  HTTP/1.1

网关/代理若收到高版本的消息,MUST降低请求的版本、报错、切换到 tunnel

不同版本之间,请求头会有一定兼容性问题

3.2 Uniform Resource Identifiers

URIs 别名: WWW addresses, Universal Document Identifiers, Universal Resource Identifiers, URL, URN
对 HTTP 来说 URL 仅仅是格式化的字符串

3.2.2 http URL

http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
port default 80
避免使用 IP 代替 host

3.2.3 URI Comparison

一个一个字节比较,并区分大小写
特殊情况
- 端口有默认值,(见RFC 2396)里的默认端口
- host 不分大小写
- scheme 不分大小写
- abs_path 为空等同与 "/"

除了"保留(reserved)"和"不安全(unsafe)"字符集里的字符(参见RFC 2396)
其他字符等效于他们的 "%HEXHEX"编码

      http://abc.com:80/~smith/home.html
      http://ABC.com/%7Esmith/home.html
      http://ABC.com:/%7esmith/home.html

3.3 Date/Time Formats

3.4 Character Sets

charset = token
charset 最好符合IETF Policy on Character Sets and Languages(https://www.rfc-editor.org/rfc/rfc2277) 的要求

----------------- demo -----------------
Content-Type: text/plain; charset=UTF-8

3.4.1 被忽略的字符集

有些 HTTP 1.0 不能处理在Content-Type头域里明确指定的字符集参数
(entity body,译注:这里翻译成“实体主体”因为Content-Type头是实体头,消息头可以分为实体头,常用头,请求头,响应头,在译文中多次用到“头”和“头域”,如消息头,消息头域,其实是同一个意思,HTTP1.1协议有时候概念并不是完全统一的)

3.5 内容编码(Content Codings)

content-coding   = token
gzip compress Welch deflate identity(default)

3.6 传输编码 (Transfer Codings)

3.6.1块传输编码(Chunked Transfer Coding)

3.7 媒体类型(Media Type)

HTTP 在头字段 Content-Type, Accept 中使用 Internet Media Types

media-type     = type "/" subtype *( ";" parameter )
type           = token
subtype        = token

Content-Type: text/html; charset=UTF-8
Media-type 必须在 IANA 注册过
未注册的媒体类型不鼓励使用

3.7.1规范化和文本缺省 (Canonicalization and Text Defaults)

HTTP应用程序 MUST 能接收CRLF,CR和LF作为文本媒体的换行符
HTTP允许应用字符集里等价于CR和LF的字节序列来表示换行符

实体主体部分可以使用 CR和LF,其他不行
默认 ISO-8859-1

3.7.2多部分类型(Multipart type)

4 HTTP Message

4.1 Message Types 消息类型

HTTP-message = Request|Response ;HTTP/1.1

格式:
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]

start-line = Request-Line | Status-Line

为了健壮性,服务器应该忽略任意请求行(Request-Line)前面的空行

某些由问题的 HTTP/1.0 实现会在请求后面加一些 CRLF
一个HTTP/1.1客户端MUST NOT在请求前和请求后加 CRLF

4.2 Message Headers

header 分类:
general-header (section 4.5)
request-header (section 5.3) 
response-header (section 6.2) 
entity-header (section 7.1)

格式:
message-header = field-name ":" [ field-value ]
field-name     = token
field-value    = *( field-content | LWS )
field-content  = <the OCTETs making up the field-value and consisting of either *TEXT or                         combinations of token, separators, and quoted-string>

 LWS 出现在 field-content 中 MAY 会被 SP 代替
 
头字段顺序的 "good practice"
    1. general-header fields
    2. request-header or response-header fields
    3. entity-header

当一个 header 有多个值,网关代理 MUST 按原来的值顺序转发。
cache-control: no-cache, no-store, no-transform

4.3 Message body 消息主体

message-body 用于承载请求和响应的 entity-body

message-body = entity-body | <entity-body encoded as per Transfer-Encoding>
Transfer-Encoding MUST 用于指定 transfer-codings
Transfer-Encoding 是消息的属性,不是实体的属性

消息主体是否出现在消息中的判断条件
1. 由 header Content-Length 或 Transfer-Encoding 来暗示。
2. request Method
3. response Method or 响应状态码(1XX 204 304)

4.4 Message Length 消息长度

message 的 transfer-length 是 message-body 的长度; 
transfer-length 由以下条件决定 (按优先级排序):
1. response message MUST NOT 包括 message-body
    such as 1xx, 204, and 304
    请求方法为 HEAD 的响应
2. Transfer-Encoding 存在, 值不为 identity。transfer-length 定义在 chunked 中(section 3.6)
3. Content-Length 存在,值为 entity-length 用 OCTETs 表示的十进制。若 entity-length 与 transfer-length 不相等,说明使用了 Transfer-Encoding。同时使用 Transfer-Encoding 和 Content-Length,Content-Length会被忽略
4. multipart/byteranges(自定义媒体),客户端需与服务端协商好传输长度。可以使用 header:Range

HTTP1.1 存在 Transfer-Encoding 

包含消息体,但是 Content-Length 不存在, 服务器 SHOULD 响应 400 (bad request) 或者 411 (length required)
MUST 接收 "chunked" 传输编码(section 3.6)
同时存在 Transfer-Encoding(值不为 identity)和 Content-Length,Content-Length MUST 被忽略

4.5 General Header Fields 常用头

有些 header 即适用于 请求,也适用于响应,但不适用与 实体。

general-header =  Cache-Control            ; Section 14.9
                | Connection               ; Section 14.10
                | Date                     ; Section 14.18
                | Pragma                   ; Section 14.32
                | Trailer                  ; Section 14.40
                | Transfer-Encoding        ; Section 14.41
                | Upgrade                  ; Section 14.42
                | Via                      ; Section 14.45
                | Warning                  ; Section 14.46

5 Request 请求

        Request       = Request-Line              ; Section 5.1
                        *(( general-header        ; Section 4.5
                         | request-header         ; Section 5.3
                         | entity-header ) CRLF)  ; Section 7.1
                        CRLF
                        [ message-body ]          ; Section 4.3

5.1 Request-Line

        Request-Line   = Method SP Request-URI SP HTTP-Version CRLF

5.1.1 Method

       Method         = "OPTIONS"                ; Section 9.2
                      | "GET"                    ; Section 9.3
                      | "HEAD"                   ; Section 9.4
                      | "POST"                   ; Section 9.5
                      | "PUT"                    ; Section 9.6
                      | "DELETE"                 ; Section 9.7
                      | "TRACE"                  ; Section 9.8
                      | "CONNECT"                ; Section 9.9
                      | extension-method
       extension-method = token
       
405 (Method Not Allowed)
501 (Not Implemented)
GET and HEAD MUST be supported

5.1.2 Request-URI

Request-URI   ="*" | absoluteURI | abs_path | authotity

OPTIONS  *  HTTP/1.1

absoluteURI
GET http://www.w3.org/pub/www/TheProject.html HTTP/1.1

abs_path
GET  /pub/WWW/TheProject.html  HTTP/1.1
Host:www.w3.org

5.2 请求资源 The Resource Identified by a Request

Internet request 资源标识通过 Request-URI 和 Host header field. 

1. Request-URI 是 absoluteURI, MUST 忽略 Host
2. Request-URI 非 absoluteURI, Host 决定 host
3. 不满足 1, 2。 response MUST 400(Bad Request) 

5.3 请求头 Request Header Fields

请求的附加消息或客户端的附加消息
request-header = Accept                   ; Section 14.1
                | Accept-Charset           ; Section 14.2
                | Accept-Encoding          ; Section 14.3
                | Accept-Language          ; Section 14.4
                | Authorization            ; Section 14.8
                | Expect                   ; Section 14.20
                | From                     ; Section 14.22
                | Host                     ; Section 14.23
                | If-Match                 ; Section 14.24
                | If-Modified-Since        ; Section 14.25
                | If-None-Match            ; Section 14.26
                | If-Range                 ; Section 14.27
                | If-Unmodified-Since      ; Section 14.28
                | Max-Forwards             ; Section 14.31
                | Proxy-Authorization      ; Section 14.34
                | Range                    ; Section 14.35
                | Referer                  ; Section 14.36
                | TE                       ; Section 14.39
                | User-Agent               ; Section 14.43

6 Response 响应

 Response      = Status-Line               ; Section 6.1
                 *(( general-header        ; Section 4.5
                 | response-header        ; Section 6.2
                 | entity-header ) CRLF)  ; Section 7.1
                 CRLF
                 [ message-body ]          ; Section 7.2

6.1 Status-Line

       Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

6.1.1 Status Code and Reason Phrase

1xx: Informational 消息 - Request received, continuing process 接收到消息,继续进程
2xx: Success 成功 - The action was successfully received, understood, and accepted
3xx: Redirection 重定向 - Further action must be taken in order to complete the request
4xx: Client Error 客户端错误 - The request contains bad syntax or cannot be fulfilled
5xx: Server Error 服务器错误 - The server failed to fulfill an apparently valid request
Status-Code = 
           |"200"   ; 10.2.1节: OK
          | extension-code

extension-code =3DIGIT
Reason-Phrase = *<TEXT,excluding CR,LF>

具体 code 见原文 https://www.rfc-editor.org/rfc/rfc2616.html#section-6.1.1

6.2 Response Header Fields

响应的附加消息或服务端的附加消息
response-header = Accept-Ranges           ; Section 14.5
                | Age                     ; Section 14.6
                | ETag                    ; Section 14.19
                | Location                ; Section 14.30
                | Proxy-Authenticate      ; Section 14.33
                | Retry-After             ; Section 14.37
                | Server                  ; Section 14.38
                | Vary                    ; Section 14.44
                | WWW-Authenticate        ; Section 14.47

7 Entity 实体

Request and Response messages MAY 传输实体,如果不受 request method 或 response status code 限制. 
entity = entity-header fields + entity-body

7.1 Entity Header Fields

       entity-header  = Allow                    ; Section 14.7
                      | Content-Encoding         ; Section 14.11
                      | Content-Language         ; Section 14.12
                      | Content-Length           ; Section 14.13
                      | Content-Location         ; Section 14.14
                      | Content-MD5              ; Section 14.15
                      | Content-Range            ; Section 14.16
                      | Content-Type             ; Section 14.17
                      | Expires                  ; Section 14.21
                      | Last-Modified            ; Section 14.29
                      | extension-header

       extension-header = message-header
       
接收方可以忽略未识别 header

7.2 Entity Body

entity-body    = *OCTET
entity-body 由 message-body 根据 Transfer-Encoding decoding 后得到

7.2.1 Type

消息体的数据类型由 Content-Encoding 和 Content-Type 指定

entity-body := Content-Encoding( Content-Type( data ) )
Content-Type 指定数据的 media type
Content-Encoding 指定 content codings

MAY 媒体类型首先看 Content-Type,其次从数据内容或URI来推断,
SHOULD 最后指定为 application/octec-stream

7.2.2 Entity Length

transfer-coding 之前的长度

8 连接 Connections

8.1 持久化连接 Persistent Connections

8.1.1 目的 Purpose

持久化连接有数个优势:
1. 减少TCP开启关闭次数, 节省路由器和主机 (hosts:clients, servers, proxies, gateways, tunnels, or caches) 的CPU time, 节省主机上 TCP protocol control blocks 占用的内存。
2. 可以在连接上开启 Pipelining。允许客户端发出多个请求而无需等待每个响应。
3. 减少报文数量,并有足够的时间确定网络拥塞(congestion)状态,减少网络拥塞
4. 后续连接,节省了三次握手
5. 报错后无需关闭 TCP 连接,可以乐观的尝试新特性。

SHOULD 实现持久化连接

8.1.2 整体操作 Overall Operation

HTTP 1.1 默认持久化连接

Persistent connections 可以使用 header Connection 来关闭 close of a TCP connection
一旦发送关闭信号, 客户端 MUST NOT 堆这条连接发送任何请求
8.1.2.1 协商(Negotiation)
HTTP/1.1 client 和 server 默认保持连接,直到请求头 Connection 携带 connection-token close
HTTP/1.0 向后兼容见 section 19.6.2 
持久化连接所有消息 MUST 携带 message length, 详情见 section 4.4
8.1.2.2 流水线Pipelining
MUST:流水线必须在持久化连接上开启
SHOULD:使用流水线时,需要使用幂等方法(see section 9.1.2)。

8.1.3 Proxy Servers

MUST: 代理不能为 HTTP/1.0 的客户端建立持久化连接

8.1.4 最佳实践 Practical Considerations

1. 需要为非活跃中的连接设置一个超时时间(time-out)。
2. SHOULD:客户端服务器超时关闭时,应该按规范关闭连接。客户端和服务器需要时刻查看对方是否关闭了连接。
3. MAY:客户端,服务器,代理可以在任何时候关闭连接。当服务器关闭连接时,客户端发起请求,建议使用重试+幂等方法保障这次请求的成功
4. 服务器的连接数建议保持在2N,
N = 同时在线用户数

以上准则都是为了降低响应时间和避免阻塞

8.2 消息传送要求 Message Transmission Requirements

8.2.1 持久化连接和流量控制 Persistent Connections and Flow Control

HTTP/1.1服务器应当保持持续连接并使用TCP流量控制机制来解决临时过载。
客户端重试会导致拥塞恶化

8.2.2 监控连接的错误状态

SHOULD:HTTP/1.1 (or later) client 发送 message-body 时应该监控 network connection 的状态。发现错误立即停止消息主体的发送。
使用 chuck 传输,可以用长度为0的块和empty trailer来结束消息。
header 上有 Content-Length MUST 马上关闭连接 

8.2.4 服务端过早关闭连接时客户端的行为

// TODO

9 方法定义

方法有很多, 此处只关注 GET POST

9.1 安全和等幂(Idempotent)方法

9.1.1安全方法

GET 获取资源时安全,action(执行动作)时不保证安全
POST 执行动作时安全

GET  查询安全
POST 增删改查都安全

9.1.2 等幂方法

GET POST 都是幂等方法
除了 error or expiration 问题,相同参数返回相同结果

9.3 GET

当请求头中包含  If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range,GET 方法语义将改为 "conditional GET"
满足条件时响应中返回实体,否则使用缓存。

GET请求的响应是可缓存的(cacheable),详情见 section 13.

使用表单时的安全问题,见 section 15.1.3

9.5 POST

功能如下:
-已存在的资源的注释;
-发布消息给一个布告板,新闻组,邮件列表,或者相似的文章组。
-提供一个数据块,如提交一个表单给一个数据处理过程。
-通过追加操作来扩展数据库。

响应可缓存,除非响应头中包含 Cache-Control 或 Expires。

10 状态码

RFC 2616:超文本传输协议 -- HTTP/1.1#section-10

11 访问认证

12 内容协商 Content Negotiation

HTTP 提供了几种内容协商的机制 -- 多种表示方式可用时,为响应选择最佳表示方式。

内容协商不是格式协商,因为 representations 可能是同样的 media type,但是利用了 media type 的不同性质,例如语言

内容协商在HTTP中由两种类型:服务器驱动协商和代理驱动协商。也可以联合使用

12.1 服务器驱动协商(Server-driven Negotiation)

通过服务器算法选择响应最好的表现形式。

12.2 代理驱动协商 (Agent-driven Negotiation)

12.3 透明协商(Transparent Negotiation)

13. 缓存 Cache

14. 请求头定义

14.7 Allow

Allow   = "Allow" ":" #Method
Allow: GET, HEAD, PUT

14.10 Connection

Connection = "Connection" ":" 1#(connection-token)
connection-token  = token
Connection: close

14.13 Content-Length

Content-Length = "Content-Length" ":" 1*DIGIT
Content-Length: 3495

限制条件见 section 4.4

14.17 Content-Type

Content-Type = "Content-Type" ":" media-type
Content-Type: text/html; charset=ISO-8859-4

......


wzyAcyy
9 声望2 粉丝