3协议参数
3.1HTTP版本
HTTP使用一个“<major>.<minor>”模式来标志协议版本。协议版本就是要允许发送者表达message格式的信息以及它理解更多HTTP协议的能力(不只是说通讯的功能)。加了不影响通讯行为的MESSAGE组件或加了扩展的域值都不必改变版本号。<minor>增大表示协议被改变,一般的MESSAGE解析算法没有变,但是增加了MESSAGE语义也就增加了发送者额外的功能。<major>增大如果MESSAGE的格式改变了。
HTTPmessage的HTTP版本在MESSAGE的头一行的版本域中被表示。
HTTP-Version =”HTTP””/”1*digit”.”1*DIGIT
注意major和minor数每一个都可以独立对待。因此HTTP/2。4比HTTP/2。13低,而HTTP/2。4又比HTTP/12。3低。前面的0必须被接收者忽略而发送者千万不要发。
一个发送包含“HTTP/1。1”版本的request或response信息必须最少与这个规范条件兼容。而一个和这个规范最少条件兼容的应用应该在他们的MESSAGE中标明HTTP/1。1版本,并且对于于HTTP/1。0不兼容的MESSAGE必须标明HTTP/1。1版本。关于什么时候送规范的HTTPV值更多细节看RFC2145[36]。
应用的HTTP版本是应用最少条件兼容的最高HTTP版本。
Proxy和gateway应用需要仔细对待转发不同于自身应用版本的message。因为过来的MESSAGE中的HTTP版本代表了发送者的协议能力,一个PROXY/GATEWAY千万不要发送一个高于该版本的MESSAGE。相反,如果接受了一个更高版本也不要减低或报错或转向TUNNEL行为。
RFC2068[33]发布时发现了与HTTP/1。0proxy交互时出现的问题,缓存proxy必须,gateway可以,tunnel千万不要升级request到他们支持的最高版本。Proxy和gateway的Response必须和那个request保持同一个版本。
注意:在HTTP版本间的转换可能包含头区某域的改变,而这些改变可能被要求或被拒绝。
3.2统一资源定位符
关于URI以前出现的名称有:WWW地址,通用文档标志,通用资源标志,最后,代表URL和URN的组合。只要和HTTP相关,URI就是一个简单的格式化字符串,通过名称,地址或其他特征来标志一个资源。
3.2.1普通语法
在HTTP中URI可以以一个绝对的形式表现或相对于一些知道的基本的URI,这取决于使用的上下文。这两种形式被区分于:绝对的URI总是以一个模式名称跟一个冒号开始。关于URL的词法和语法的绝对定义信息,需要看“Uniform Resource Identifiers (URI): Generic Syntax and Semantics,” RFC 2396 [42](取代了RFCs1738[4]和RFC1808[11]);而其中的部分定义“URI-reference”, “absoluteURI”, “relativeURI”,“port”, “host”,“abs_path”, “rel_path”, 和 “authority”在本规范中也被使用。
HTTP协议并没有对URI的长度有一个预先的限制。服务器必须能够处理任何他们提供资源的响应URI,而且应该能够处理无限长度的URI,如果他们提供基于GET的表达形式。一个服务器应该返回414如果一个URI比服务器能处理的URI还长的话。
注意:服务器应该小心对待长度超过255个字节的URI,因为一些老client和proxy实现可能不支持这些长度。
3.2.2http URL
“http”模式被用来通过HTTP协议定位网络资源。下面为httpURL定义了模式化的词法和语法.
http_URL = "http:" "//" host [ ":" port ] [ abs_path [ "?" query ]]
如果端口空或为给出,使用80。语法就是,资源所在的server在host的port端口监听tcp连接,而abs_path指定了请求资源的Request-URI。IP地址的使用只要有可能就应该被避免(RFC1900[24])。如果abs_path没有出现在URL中,它必须作为“/”作为Request-URI(SEC5。1。2)。如果一个代理接受到不完全domain名称的主机名称,它可以用它自己的domain名称加进去;如果接受到完整的,则不能改变主机名称。
3.2.3URI比较
当把两个URI比较以决定他们是否匹配,一个client应该采用大小写敏感地字节对应字节地方式比较整个URI,下面除外:
端口默认为80,有没有相同
host名称必须大小写不敏感
模式名称必须大小写不敏感
一个空的abs_path等同于一个“/”的abs_path
不在“reserved” and “unsafe”字符集里的字符等价与“% HEX HEX”编码。例如
http://abc.com:80/~smith/home.html
http://ABC.com/%7Esmith/home.html
http://ABC.com:/%7esmith/home.html
等价的。
3.3Data/Time 格式
3.3.1完整日期
HTTP应用历史上允许3中不同的DATE/TIME表示:
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
第一种多用于INTERNET标准并且代表了RFC1123[8](RFC822[9]的更新)的固定长度子集。
第二种被普遍使用,但是基于被废弃的RFC850[12]日期格式并且缺少年度的4位表示。HTTP/1.1clients 和server解析date值就必须接受所有3种格式,虽然必须的是在HTTP头区按RFC1123产生日期值。SEC19.3。
注意:date值的接收程序被鼓励可以接受非HTTP应用发的DATE值,这种情况经常出现在通过SMTP/NNTP的代理或网关接收或发送信息。
3.2.2 delta秒
一些HTTP头区允许一个时间值被一个秒的整数值来表示,十进制,在message被接收到之后。
3.4 字符集
HTTP使用MIME描述的相同定义来定义字符集。
在这篇文档中,术语字符集指使用一个或多个表把一组字节码转换成一组字符的方法。注意相反方向的无限制的转化不是必需的,并不是所有的字符都在一个给定字符集中,并且一个字符集可以提供多个字节码组合来代表一个指定字符。这个定义用来允许多种字符编码,从简单的单表映射如US-ASCII到复杂表的转化如ISO-2022技术。但是,和MIME字符集名称定义相关的定义必须完整地明确从字节码到字符的映射。具体地说,使用外面的相关信息来确定精确映射是不允许的。
注意:更常使用字符编码来指字符集。但是因为HTTP和MIME使用相同的登记,所以术语最好统一起来。
HTTP字符集用大小写不敏感的标记来标志。完整的标记组合由IANACharacter Set registry [19]来定义。
Charset=token
虽然HTTP允许任意的TOKEN,凡是IANA Character Set registry [19]中定义的组合值必须代表其中注册的字符集。应用应该仅使用那些在IANA登记中的字符集。
实现者要意识到IETF[38][41]。
3.4.1没有CHARSET
一些HTTP/1。0软件认为没有CHARSET参数的CONTENT-TYPE头应该“由接收者来猜”。这并不正确。发送者如果要阻止这种行为应该包含一个参数即使字符集是ISO-8859-1而且如果不会迷惑接收者也应该这样做。
不幸的是一些更老的HTTP/1。0CLIENT不能合适地处理CHARSET参数。HTTP/1。1接收者必须采用发送者提供的该参数;而且那些可以猜的用户端初始展示一个文档时也必须使CONTENT-TYPE区里的字符集,而不是自己爱咋咋地。
3.5内容编码
内容编码值来指示一个可以被用到一个ENTITY上的编码转换。内容编码主要被使用来允许一个文档被压缩或不丢失媒体类别信息和其他信息的转化。ENTITY被编码地存储,直接发送,然后只被接收者解码。
content-coding = token
token是大小写不敏感的。HTTP/1。1在Accept-Encoding(section 14.3)和Content-Encoding (section 14.11)使用该值。尽管该值描述了内容编码,更重要的是它指定了什么样的解码是合适的。
IANA登记了内容编码值。起初,登记包含了下面这些标记:
Gzip 一个编码样式,由文件压缩程序GZIP(GNU ZIP)提供,RFC1952[25]描述。这个格式是LZ77和32CRC编码。
Compress
有UNIX文件压缩程序“compress”来提供。格式是LZW编码。
使用程序名字来标志编码格式并不理想,也将在未来的编码中被取代。在这里使用是历史的原因,并不是个好设计。为了向前兼容,一个应用应该把“x-zip”和“x-compress“认为和”gzip“”compress”认为是各自相同的。
Deflate
“zlib“(RFC1950[3]定义)和”deflate“压缩机制(RFC1951[29]定义)的组合。
Identity
默认的编码;没有转化的转化。只在Accept-Encoding头中使用,不应在Content-Encoding中使用。
新的内容编码值应该被登记;为了允许交互性,对新值的内容编码算法应该是可公共使用并足够用来独立实现,并且要满足内容编码存在的初衷。
3.6传输编码
传输编码被用来指示一个用来保证ENTITY穿越网络安全传输的编码。它是MESSAGE的一个属性并不是原始的ENETITY的。
transfer-coding = "chunked" | transfer-extension
transfer-extension = token *( ";" parameter )
parameter以属性值对的形式存在。
parameter = attribute "=" value
attribute = token
value = token | quoted-string
所有的传输编码值是大小写不敏感的。HTTP/1。1在TE(sec14.39)和Transfer-Encoding(SEC14。41)中使用。
只要一个传输编码被应用在一个MESSAGE-BODY中,该编码集合必须包含“CHUNKED“,除非message因关闭连接而结束。当”chunked“被使用,他必须是对MESSAGE-BODY的最后的编码。绝对不能用两次。靠这个接受者可以决定MESSAGE的传输长度(SEC4。4)。
MEME[7]的Content-Transfer-Encoding值,用来通过7位传输服务来实现2进制数据安全传输。虽然传输编码类似于这种安全传输,但是,安全传输在8位传输协议有一个不同的焦点。在HTTP传输中不安全的问题主要在决定BODY的长度和加密数据。
IANA登记了传输编码值。最初,包含“chunked” (section 3.6.1), “identity” (section 3.6.2), “gzip” (section3.5), “compress” (section 3.5), and “deflate” (section 3.5)。新登记也应该和内容编码一样登记。
一个server,如果接收了无法处理的传输编码,应该返回501,并且关闭连接。一个server绝对不能发给HTTP1。0客户端传输编码。
3.6.1大块的传输编码
修改BODY改成一块一块的序列,每一个带大小指示,带一个可选的尾部,里面有ENTITY-HEADER区。这允许动态地产生的内容也被接收者识别组装好。
Chunked-Body = *chunk
last-chunk
trailer
CRLF
chunk = chunk-size [ chunk-extension ] CRLF
chunk-data CRLF
chunk-size = 1*HEX
last-chunk = 1*("0") [ chunk-extension ] CRLF
chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)
trailer = *(entity-header CRLF)
chunk-size区是十六进制数字用来表示块的大小。编码以一个大小为0,跟着一个空行结束的尾部的块来作为结束。
尾部允许发送者来在MESSAGE结束出包括额外的HTTP头区。而TRAILER头区可以用来知识哪个头区被包含在了一个尾部(SEC14。40)
一个server如果使用块传输编码,决不能为头区使用尾部,除非下面至少一个是真的。
a)request包含一个TE头区,指示在response的传输编码中尾部是可以接受的。
b)server是response的origin server,尾部整个由可选元数据,而接收者可以不接收这些元数据也能使用MESSAGE。换句话说,ORIGIN SERVER愿意接收在client传递过程中尾部被割掉的信息。
这个要求阻止了一些通过了HTTP/1。1(或更高版本)而被HTTP/1。0接收时出现的交互错误。这样就不会强于要求代理实现一个无限大小的缓存。
App19.4.6展示了一个解码Chunked-Body的例程。
所有的HTTP/1。1应用必须能够接收并解码CHUNKED传输编码,并且必须忽略他们不理解的chunk-extension扩展。
3.7媒体类型
HTTP使用IMT[17]在Content-Type (section 14.17) and Accept (section 14.1) 头区中提供开放和灵活扩展的数据类型和类型交互。
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token
参数可以以attribute/value的形式来跟随type/subtype
ype, subtype, 和 parameter属性名称都是大小写不敏感的。参数值可以是或不是到小写敏感,这取决于参数名称对应的语法。LWS决不能在type和subtype之间被使用,也不能在attribute和它的value之间使用。参数的存在与否可能会对media-type的处理有很重要的意义,这取决于其在登记中的定义。
注意一些老的HTTP应用不会认出该媒体类型参数。当发送数据给这些应用时,实现应该只使用那些被定义要求使用的TYPE/SUBTYPE。
MEDIA-TYPE在(IANA [19])中定义。登记过程在RFC1590[17]中被概括。使用非登记的media tyoe是不提倡的。
3.7.1标准化和默认文本
国际媒体类型用一个标准形式登记。一个entity-body在通过HTTPmessage传递前必须作为相应的标准形式存在。 “text”类型例外,我们将在下一段说明。
在标准形式下,“text”的子类使用CRLF作为文本行的连接。HTTP放松了这个要求,允许在一个完整的entity-body中始终用“CR”或“LF”单独代表行连接。HTTP应用对于通过HTTP接收到的文本必须能够使用CRLF,CR,LF作为行连接的代表。另外,如果文本使用的字符集并不使用13,10代表CR,LF,就象在一些多字节字符集那样,那么,HTTP允许使用其对应的字节码代表该字符。这种灵活性
3.7.2多部分类型
MIME提供了许多“multipart”类型—用一个message封装一个或多个entity。所有的multipart共享一个公共的语法(sec5.1.1-RFC2046[40]),并且必须包含一个分界参数作为media类型值的一部分。Message本身是一个协议元素因此必须进使用CRLF去作为跨BODY-PART的行继续标志。不同于在RFC2046,任何多部分类型的MESSAGE的尾部必须是空的;HTTP应用绝对不能传递尾部。(即使原先的多部分包含一个尾部)。这个限制的存在是为了保持多部分消息体的自分界性质,就是信息体的结束使用多部分的结束作为结束。
一般情况下,HTTP对于一个多部分消息体是和其他的一样严格作为有效负荷处理的。有个例外是“multipart/byteranges”(appendix19.2)当它出现在206response中时,会被一些HTTP缓存机制象在sec13.5.4和14.16中描述地那样处理。在其他情况下,一个HTTPuser agent 应该类似于一个MIME用户接收一个多类型那样处理。除了那些在MIME语义中定义的那些,在每个多部分消息体中的MIME头区对于HTTP没有任何意义。
一般情况下,一个HTTPuser agent应该象MIME一样处理多部分类型。如果一个应用接受到一个不认识的multipart subtype,它必须把它等同与“multipart/mixed”处理。
注意:“multipart/form-data”已经被明确定义用来通过POST方法传递表单数据,RFC1867[15]。
3.8产品标记
产品标记被用来允许通讯应用来通过软件名称和版本来标志他们自己。大多数使用产品标记的区也使用子产品来形成被列出的应用的重要组成部分,它们以空格分开。按照其重要程度来有序列出。
product = token ["/" product-version]
product-version = token
例如:
User-Agent: CERN-LineMode/2.15 libwww/2.17b3
Server: Apache/0.8.4
产品标记应该言短意赅。它们绝对不能被用来做广告或其他不重要的信息。虽然任何的标记字符可以出现在一个product-version里,这些个字符应该只用来标记版本。(例如,接续的版本好应该只在产品版本部分不同)。
3.9属性值
HTTP content negotiation(SEC12)使用短浮点数来标记各种negotiable参数的重要性(权重)。一个权重回被标准化成一个>0并且<1的数。如果一个参数是0的质量值,那这个参数的内容是不被客户端所接受的。HTTP/1。1应用绝对不能产生多于小数点后3位的数。用户对他们的值的配置也应该限于此
qvalue = ( "0" [ "." 0*3DIGIT ] )
| ( "1" [ "." 0*3("0") ] )
其实这个名字本身容易引起误解,因为其值仅仅代表要求质量的相对级别。
3.10语言标记
一个语言标记被用来标志人们说的语言。当然计算机语言肯定不被包含在内。HTTP在Accept-Language 和 Content-Language区使用语言标记。
HTTP语言标记的语法和登记和RFC1766[1]定义的类似。总之,一个语言标记是由1或多个部分组成:一个主语言标记和一个可能的空子标记序列:
language-tag = primary-tag *( "-" subtag )
primary-tag = 1*8ALPHA
subtag = 1*8ALPHA
空格在标记中不被允许并且所有的标记都是大小写不敏感的。语言标记命名空间在IANA中管理。例如:
en, en-US, en-cockney, i-cherokee, x-pig-latin
任何2字母的主标记是一个ISO-639语言缩写,而任何2字母的初始子标记是一个ISO-3166国家码。(后3个没有登记,最后一个不会被允许)。
3.11实体标记
实体标记用来比较来自相同的去请求资源的两个或多个实体。HTTP/1。1在ETag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), 和If-Range
使用实体标记。
如何定义以及怎么作为缓存校验来比较在sec13.3.3中描述。
entity-tag = [ weak ] opaque-tag
weak = "W/"
opaque-tag = quoted-string
如果同一资源的两个ENTITY具有相同的位集可以共享“strong entity tag”。
而由一个"W/" 前缀表示的“weak entity tag”标记的tag,如果是相等的并可以在语义上无修改地互相取代,那么可以共享一个标记。只能用来弱比较。
在一个给定resource中的对应实体必须保持实体标记具有唯一性。但是如果是不同URI得到的实体可以有相同标记值,但不表示这些实体是等价的。
3.12范围单位
HTTP/1。1允许一个client只是response实体的部分被包含在response中。HTTP/1。1在Range (section 14.35) 和Content-Range (section 14.16)中使用范围单位。一个实体能够根据各种结构单位分成多个范围
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
在HTTP/1。1定义的唯一的范围单位是”byte”。HTTP/1。1的实现可以忽略其他范围定义。HTTP/1。1被设计成允许那些不必知道范围单位的应用的存在。