Apr 13

* 消息类型
  HTTP消息由从客户端到服务器的请求和从服务器到客户端的响应组成。
  HTTP-message = Request | Response ; HTTP/1.1 messages
  Request和Response 消息使用 RFC  822  [9]的 generic-message格式来传输实体 (消息负载)
  generic-message = start-line *(message-header CRLF) CRLF [ message-body ]
  两种消息全由start-line、 0 个或多个头部域 (还称为 “头部”), 空行 (如,CRLF前没有任何东西的行)表示头部域结束,和可能的 message-body。

** Request  
  在消息的首先中,从客户端到服务器的请求消息包括应用到资源的方法、资源的标识符和使用的协议版本。
  Request = Request-Line *(( general-header | request-header | entity-header ) CRLF) CRLF [ message-body ]

** Response
  在接收并解析请求消息后,服务器以 HTTP响应消息响应。
  Response = Status-Line *(( general-header  | response-header | entity-header ) CRLF) CRLF [ message-body ] ;


* Request-Line
   Request-Line 始于方法符号,接收是 Request-URI 和协议版本,由 CRLF 结束。元素间用SP字符(空格)分隔。除了最终的CRLF序列,不允许CR或 LF
   Request-Line = Method SP Request-URI SP HTTP-Version CRLF
  
** Method
   Method符号指出在由Request-URI标识的资源上所执行的方法。方法是大小写敏感的。 
   Method = "OPTIONS"
        | "GET"
        | "HEAD"
        | "POST"
        | "PUT"
        | "DELETE"
        | "TRACE"
        | "CONNECT"
        | extension-method   
   资源允许的方法列表能够在Allow头部域中规定。响应的返回码始终通知客户端资源当前是否允许该方法,由于允许方法集能够动态改变。如果原始服务器知道该方法便所请求资源不允许,则原始服务器【应该】返回状态码 405(Method Not Allowed),如果原始服务器不认识该方法或没有实现,则返回 501(Not  Implemented) 。所有通用目的服务器【必须】支持 GET 和 HEAD 方法。所有其它方法是【可选的】;然而,如果实现了上面的方法,则【必须】按9节中规定的相同语义来实现它们  

** Request-URI
   Request-URI是统一资源标识符,标识应用到请求上的资源。
   Request-URI = "*" | absoluteURI | abs_path | authority
   Request-URI的4个选择取决于请求的特性。 星号 “*” 意思是请求不应用到特定的资源,而是服务器自己,且只在所使用的方法没必要应用到资源时允许。一个例子可能是
   OPTIONS * HTTP/1  
   当请求由代理作出时,absoluteURI形式是【要求的】 。请求代理转发请求或从有效缓存来服务它,并返回响应。要注意,代理【可以】转发请求到其它代理或直接到由 absoluteURI规定的服务器。为了避免循环请求,代理【必须】能够认识所有它的服务器名称,包括任何别名,本地变称、和数字IP地址。
   GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
   为了允许在以后的HTTP版本中对所有请求中的absoluteURI进行转换,所有HTTP/1.1服务器【必须】在请求中接受 absoluteURI 形式,即使 HTTP/1.1 客户端将只在向代理请求时生成它们
   只有CONNECT方法,使用 authority形式。
   Request-URI 最通用的形式用于标识原始服务器或网关上的资源。在这种情况下,URI的绝对路径 (见3.2.1节, abs_path) 【必须】 传送为 Request-URI, URI的网络地址 (authority)【必须】在 Host 头部域中传送。例如,客户端希望直接从原始服务器上获取资源,可以创建端口号80的TCP连接到主机“www.w3.org”并发送消息行:
   GET /pub/WWW/TheProject.html HTTP/1.1
   Host: www.w3.org
   接着是Request的余下部分。要注意,绝对路径不能为空;如果原始 URI中不存在,则它【必须】给出“/”(服务器根)。
   Request-URI以3.2.1节中规定的格式传输。如果Request-URI使用“% HEX HEX”编码方式  [42]来编码,则原始服务器【必须】解码 Request-URI,以便正确解析请求。服务器【应该】以适当的状态码响应无效的Request-URI。 【禁止】透明代理在转发请求到入界服务器时重写所收到的Request-URI的“abs_path” 部分, 除非上面说明的替换空abs_path为 “/”
   注意:当原始服务器为保留目的不正确使用非保留 URI字符时,“不重写”规则阻止代理改变请求的意思。实现者应该清楚,已知一些早期HTTP/1.1代理会重写 Request-URI。
   因特网请求标识的确切资源是由检查 Request-URI 和 Host 头部域判断的。原始服务器不允许资源与请求主机不同, 【可以】在判断由 HTTP/1.1 请求标识的资源时乎略 Host 头部域值(HTTP/1.1 支持Host的其它要求还可见 19.6.1.1节)。原始服务器要区别对待基于主机请求的资源(有时候用作虚拟主机或空主机名) 【必须】例如如下的规则来判断 HTTP/1.1请求所请求的资源:
   1.如果Request-URI是absoluteURI,主机是 Request-URI的一部分。 【必须】乎略请求中的任何Host头部域值
   2.如果 Request-URI 不是 absoluteURI,且请求包括 Host 头部域,则主机由 Host 头部域值决定
   3.如果规则1或2决定的主机在服务器上不是有效的主机, 则响应 【必须】 是 400 (Bad Request)错误消息
   缺少Host头部域的HTTP/1.0 请求的接收方【可以】尝试使用启发式(如,为某些统一到特定的主机检查URI的路径)判断正请求的确切资源。



* Status-Line
   Request 消息的首行是 Status-Line,由协议版本,接着数字状态码和相关的文本短语组成,每个元素间由SP字符分隔。除了最后的 CRLF序列,不允许CR或 LF。
   Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

** Status-Code和Reason-Phrase   
    Status-Code 元素是 3 位整数结果码,尝试理解和满足请求。这此代码的完整定义在 10节中。Reason-Phrase意图给出简短的Status-Code的文本描述。Status-Code意图用在自动控制,Reason-Phrase意图给人类用户。不要求客户端检查或显示 Reason-Phrase。
    Status-Code 的首位数字定义响应的类别。最后两个数字没有任何分类。首位数字有 5个值:
    | 1xx | 信息性——收到请求,继续处理                   |
    | 2xx | 成功性——成功收到、理解并接受行动             |
    | 3xx | 重定向——必须采取进一步行动来完成请求         |
    | 4xx | 客户端错误——请求包含错误语法或不能完成       |
    | 5xx | 服务器错误——服务器没有成功完成显然有效的请求 |
    HTTP/1.1 定义了数字状态码的单个值,下面介绍相应的 Reason-Phase 集的例子。这里列出的原因短语只是推荐的—— 【可以】 不影响协议的情况下用本地化等价的短语替换它们。
    Status-Code = "100" ; 10.1.1节: Continue
                   | "101" ; Switching Protocols             |
                   | "200" ; OK                              |
                   | "201" ; Created                         |
                   | "202" ; Accepted                        |
                   | "203" ; Non-Authoritative Information   |
                   | "204" ; No Content                      |
                   | "205" ; Reset Content                   |
                   | "206" ; Partial Content                 |
                   | "300" ; Multiple Choices                |
                   | "301" ; Moved Permanently               |
                   | "302" ; Found                           |
                   | "303" ; See Other                       |
                   | "304" ; Not Modified                    |
                   | "305" ; Use Proxy                       |
                   | "307" ; Temporary Redirect              |
                   | "400" ; Bad Request                     |
                   | "401" ; Unauthorized                    |
                   | "402" ; Required                        |
                   | "403" ; Forbidden                       |
                   | "404" ; Not Found                       |
                   | "405" ; Method Not Allowed              |
                   | "406" ; Not Acceptable                  |
                   | "407" ; Proxy Authentication Required   |
                   | "408" ; Request Time-out                |
                   | "409" ; Conflict                        |
                   | "410" ; Gone                            |
                   | "411" ; Length Required                 |
                   | "412" ; Precondition Failed             |
                   | "413" ; Request Entity Too Large        |
                   | "414" ; Request-URI Too Large           |
                   | "415" ; Unsupported Media Type          |
                   | "416" ; Requested range not satisfiable |
                   | "417" ; Expectation Failed              |
                   | "500" ; Internal Server Error           |
                   | "501" ; Not Implemented                 |
                   | "502" ; Bad Gateway                     |
                   | "503" ; Service Unavailable             |
                   | "504" ; Gateway Time-out                |
                   | "505" ; HTTP Version not supported      |
                   | extension-code                          |
    extension-code = 3DIGIT
    Reason-Phrase = *<TEXT,除CR, LF外>
    HTTP状态码可扩展。不需要HTTP应用程序理解所有注册状态码的含义,尽管这种理解显然是期望的。然而,应用程序【必须】理解任何状态码的类别,由首位数字指出,并对待任何不认识的响应等同为该类的x00状态码,除了【禁止】缓存不认识的响应。例如,如果客户端收到不认识的状态码431,则它可能安全地假设它的请求有一些错误,并对待该响应为如同它已经收到400状态码。在这种情况下,用户代理【应该】为用户呈现返回的响应中的实体,由于该实体很可能包含人类可读的信息,其中会解释该非正常状态



* message-header
  HTTP 头部域,包括 general-header 、request-header 、response-header 、和entity-header域,按 RFC 822 [9]的 3.1节中给出的相同的一般格式。敏个头部域由一个跟着冒号(“:” )的名称和域值组成。域名是大小写不敏感的。域值【可以】由任何数量的LWS引导,尽管首选是单个 SP。头部域能够扩展到多行,通过用至少一个SP或 HT引导扩展行。应用程序应该按“通用形式”,已知或指出的,当生成 HTTP构造时,由于可能存在一些实现不能接受非通用形式的任何东西。
  message-header = field-name ":" [ field-value ]
  field-name = token
  field-value = *( field-content | LWS )
  field-content = <组成field-value的 OCTET, 和*TEXT的组成或组合 token、separators和 quoted-string的组成>
  field-content 不包括任何前导或结尾的 LWS:线性空白符出现在 field-value 的首个非空白字符前或field-value的最后的非空白字符后。 【可以】删除这种前导或结尾的 LWS而一改变field-value的语义。在解析field-value或转发消息到下游前【可以】将出现在 field-content间的任意个LWS替换为单个SP。
  收到不同 field-name 头部域的顺序没有意义。然而,“好实践”结果是,首先发送general-header,接着是request-header 或 response-header 域,最后是 entity-header 域。
  多个field-name相同的 message-header 域【可以】出现在一个消息中,当且仅当该头部域的整个 field-value 定义为逗号分隔的列表 [如,#(值)] 时。 【必须】能够组合多个头部域为单个“field-name:  field-value”对,而不改变消息的语义,通过追加每个后序 field-value到第一个,之间由逗号分隔开。因此收到相同 field-name 头部域的顺序对于组合 field-value的解析是有意义的,因此代理【禁止】在转发消息时改变这些 field-value的顺序。

** request-header 域
   request-header 域允许客户端传输关于请求和关于客户端自己的额外信息给服务器。这些域拌演请求修饰符,与编程语言方法符号上的参数有相同的语义。
   request-header =  Accept ;
   | Accept-Charset
   | Accept-Encoding
   | Accept-Language
   | Authorization
   | Expect
   | From
   | Host
   | If-Match
   | If-Modified-Since
   | If-None-Match
   | If-Range
   | If-Unmodified-Since
   | Max-Forwards
   | Proxy-Authorization
   | Range
   | Referer
   | TE
   | User-Agent
   request-header 域名能够靠与协议版本修改一起扩展。然而,当通迅中所有成员都认识这些 request-header 域时, 【可以】为 request-header 域的语义给出新的或实验性头部域。不认识的头部域将作为entity-header 域对待。
 
** response-header 域
   response-heder 域允许服务器传递不能放在 Status-Line 中的关于响应的额外信息。这些头部域给出关于服务器和关于对Request-URI所标识资源的以后访问。
   response-header = Accept-Ranges ; 14.5节
                         | Age                |
                         | ETag               |
                         | Location           |
                         | Proxy-Authenticate |
                         | Retry-After        |
                         | Server             |
                         | Vary               |
                         | WWW-Authenticate   |
   response-header 域名可能与协议版本修改一起可靠的扩展。然而,当通迅中所有成员都认识这些response-header 域时, 【可以】为 response-header 的语义给出新的或试验性头部域。不认识的头部域按entity-header 对待。
 
** general-header
   有几个头部域一般可应用于请求和响应消息上,但不应用到传输的实体上。这些头部域只应用到正在传输的消息上。
   general-header = Cache-Control
                 | Connection        |
                 | Date              |
                 | Pragma            |
                 | Trailer           |
                 | Transfer-Encoding |
                 | Upgrade           |
                 | Via               |
                 | Warning           |
   只有与协议版本同时修改时,general-header 域名才能可靠地扩展。然而,新的或试验性头部域可以给出到 general-header 域的语义中,如果通迅中的所有对象识别它们是general-header 域。不认识的头部域作为 entity-header 域对待

  
* message-body
  HTTP消息的 message-body(如果存在)用于挟带与请求或响应相关联的 entity-body。message-body 只有在应用了 transfer-coding 时,通过 Transfer-Encoding 头部域指出(14.41节),与entity-body不同。
  message-body = entity-body | <按每个 Transfer-Encoding编码的 entity-body>
  Transfer-Encoding【必须】用于指出任何应用程序所应用的 transfer-coding 来确保安全和正确的消息传输。Transfer-Encoding是消息的属性,不是实体和,因此请示/响应链上的任何应用程序【可以】增加或删除它。(然而,3.6 节作出一些关于使用确知的 transfer-coding时的限制。)
  当允许消息中有message-body时的规则对于请求和响应而言是不同的
  请求中存在 message-body 的信号由在请求的 message-header 中引入 Content-Length 或Transfer-Encoding来指示。如果请求方法(5.1.1节)的规定不允许在请求中发送 entity-body时, 【禁止】在请求中包括 message-body。服务器【应该】读取和转发任何请求上的message-body;如果请求方法没有包括entity-body的已定义语义时,在处理请求时【应该】乎略message-body。
  对于响应消息,消息是否包括 message-body 既取决于请求方法,也取决于响应状态码(6.1.1 节)。对 HEAD 请求方法的所有响应【禁止】包括 message-body,即使存在的entity-header 域可能使接收方确信其中包括 message-body。所有 1xx(信息性) 、204(No Content) 、和304(Not Modified)响应【禁止】包括message-body。所有其它响应确实包括message-body,即使其长度【可以】是 0。
 





* entity
  如果请求方法或响应状态码没有其它限制的话,Request和 Response消息【可以】传输实体。实体由entity-header 和entity-body组成,尽管一些响应只包括 entity-header。
  在本节中,发送方和接收方引用为客户端或服务器,取决于谁发送和谁接收实体。
** entity-header 域  
   entity-header域定义关于entity-body的元信息, 或当主体不存在时关于请求标识的资源。该元信息中的一些是【可选的】;一些可能是【要求的】 ,由该规范的各部分定义。
   entity-header = Allow
                | Content-Encoding |
                | Content-Language |
                | Content-Length   |
                | Content-Location |
                | Content-MD5      |
                | Content-Range    |
                | Content-Type     |
                | Expires          |
                | Last-Modified    |
                | extension-header |
   extension-header = message-header
   extension-header 机制允许定义额外的 entity-header 域而不改变协议, 但不能假设接收方认识这些域。接收方【应该】乎略不认识的头部域,且透明代理【必须】转发它。
  
** entity-body   
   entity-body(如果有)按 entity-header 域定义的格式和编码与 HTTP 请求或响应一起发送。
   entity-body = *OCTET
   entity-body只出现在存在 message-body的消息中。entity-body通过解码任何可能应用以确保安全和正确传输消息的 Transfer-Encoding的 message-body来获取。
  
*** 类型
    当entity-body包括在消息中,则其数据类型由头部域 Content-Type和 Content-Encoding决定。这里定义2层,按顺序的编码模型:
    entity-body := Content-Encoding( Content-Type( data ) )
    Content-Type 规定下层数据的媒体类型。Content-Encoding 可用于指出应用到数据上的任何额外内容编码,通常为数据压缩用途,它是所请求资源的属性。没有缺省的编码。
    包含entity-body的任何HTTP/1.1消息都【应该】包括 Content-Type头部域来定义该主体的媒体类型。当且仅当没有 Content-Type给出媒体类型时,接收方【可以】通过检查用于标识资源的 URI 的内容和/或其扩展名尝试猜测媒体类型。如果媒体类型还是未知,则接收方【应该】将其按“application/octetstream”类型对待。
   
*** entity-length
    消息的entity-length是在应用任何transfer-coding 前 message-body的长度。 4.4节定义如何判断message-body的transfer-length。