工作,学习,生活,这里将会有一些记录. 备用域名:http://meisw.51099.com 注册 | 登陆
浏览模式: 标准 | 列表2012年10月的文章

sed的一些总结

在写一些常用的脚本中,经常会用到sed,但是这东西,不经常用,就会忘掉,现在记在这里,以后想找sed了就来这里看看。
*替换
sed ‘s/word1/word2/2′ file 将第2行中的word1替换为word2
sed ‘s/word1/word2/g’ file word1全局替换为word2
sed -n ‘s/word1/word2/p’ file 全局替换并打印
sed ‘s/word1/word2/w test’ file 全局替换并写入文件test
sed ‘s/\/bin\/bash/\/bin\/sh/’ /etc/passwd 路径替换 特殊字符需要转义
sed ‘s!/bin/bash!/bin/sh!’ /etc/passwd 同上 感叹号被用作定界符
sed ‘ns/word1/word2/’ file 指定替换file文件中的第n行
sed ‘m,ns/word1/word2′ file 指定替换file文件中的第m到n行
sed ‘n,$s/word1/word2′ file 指定替换file文件中的第n到最后一行
sed ‘/word1/s/bash/sh/’ file 指定替换出现word1行的bash替换为sh
sed ‘n{
>s/word1/word2
>s/word3/word4
}’ file 指定替换第n行中的word1为word2 word3为word4
sed ‘s/word1/word2/;s/word3/word4/’ file 同上
sed ‘n,${
>s/word1/word2
>s/word3/word4
}’ file 指定替换从第n开始到最后一行结束的word1为word2 word3为word4
sed -e ‘n,$s/word1/word2/;s/word3/word4/’ file 同上
*删除
sed ‘d’ file 清空所有数据流(不是清空file文件内容)
sed ‘nd’ file 删除第n行
sed ‘m,nd’ file 删除第m到n行
sed ‘n,$d’ file 删除从n到最后一行
sed ‘/word1/d’ file 删除匹配word1的行

*插入
sed ‘nirhel007′ file 将rhel007插入到第n行之前
sed ‘nathis is a test’ file 将this is a test 插入到第n行之后
sed ‘$irhel007′ file 插入到最后一行之前
sed ‘$arhel007′ file 插入到最后一行之后

*更改
sed ‘ncthis is a test’ file 将第n行更改为this is a test
sed ‘/this is a test/cthat is a test’ file 匹配更改

*变换
sed ‘y/123/456/’ test
匹配修改 1-4,2-5,3-6 单个字符进行全局匹配

*打印
sed -n ‘/word/p’ file 全局匹配打印
sed -n ‘m,np’ file 打印m到n行
sed ‘=’ file 打印行号
sed -n ‘l’ file 打印不可打印的ANSIC字符
sed -n ‘np’ file 打印第n行
sed -n ‘$p’ file 打印最后一行

*文件操作
sed ‘m,nw test’ file 将file的m到n行写入到test中
sed -n ‘/word/w test’ file 匹配将包含word字符的写入test文件
sed ‘nr test’ file 将test文件中的内容写入file文件的第n行之后
sed ‘/word/r test’ file 将test文件中的内容匹配到word内容之后
sed ‘$r test’ file 将test文件中的内容追加到file的最后
sed -n ‘{
1!G
h
$p
}’ file 行逆序
sed -n ‘s/cat/”cat”/’ file 给文本中的cat增加双引号
sed -n ‘s/.at/”&”/g’ file 给文本中的.at的原单词上增加双引号
sed ‘G’ file 增加一行空行
sed ‘$!G’ file 在文本的最后一行不再增加空行
sed ‘/^$/d;$!G’ file 文本中的空行不增加行距
sed ‘=’ file 行计数
sed ‘=’ file | sed ‘N;s/\n/ /’ 计数和行在同一行上
sed -n ‘s/<[^>]*>//g;/^$/d’ file 去除html中的标签和空行

*sed正则表达式
1. .*{}[]^$\+?| 这些特殊的字符需要用\转义
2. 定位符
sed -n ‘/^test/p’ file 匹配test开头的行
sed -n ‘/test$/p’ file 匹配test结尾的行
sed -n ‘/^this is a test$/p’ 匹配以test开头和结尾的行
sed -n ‘/^$/d’ file 去掉空行
3 点字符
sed -n ‘/.li/p’ file 匹配除了换行之外的所有字符
4 字符类
[]代表或者的意思
sed -n ‘/[ch]at/p’ file 匹配hat或者cat的单词
sed -n ‘/[Yy][Ee][Ss]/p’ 匹配任何形式的yes
sed -n ‘/[c-h]at/p’ file
sed -n ‘/[a-ch-m]/p’ file 匹配a-c,h-m开头的单词
sed -n ‘/^[0-9][0-9][0-9][0-9][0-9][0-9]$/p’ 匹配邮编,电话
5 否定字符类
sed -n ‘/[^ch]at/p’ 不匹配以cat和hat开头的单词
sed -n ‘/cat/!p’ 不匹配匹配cat的行
6 * 前面的字符不出现或者出现多次

 

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

搜索并替换

sed -i '/memory_limit/s/128/64/' /www/wdlinux/etc/php.ini

客户端缓存分析

Expires(过期时间)

Http 头信息设置过期时间,一般是设置一个时间点,例如:

Expires:Tue Jul 28 11:00:00 CST 2011 (2011/7/28)

一般使用在静态文件,例如img、js、css等。

要注意的:如果设置的过期时间是一个固定的时间,在返回内容的时候又没有连带更新下次过期的时间,那么之后都会请求服务器,反而增加了负载和响应时间。

Cache-Control(缓存控制)

缓存控制,使用起来更为灵活、功能更强大。

l  max-age=[秒] — 执行缓存被认为是最新的最长时间。类似于过期时间,这个参数是基于请求时间的相对时间间隔,而不是绝对过期时间,[秒]是一个数字,单位是秒:从请求时间开始到过期时间之间的秒数。

l  s-maxage=[秒] — 类似于max-age属性,除了他应用于共享(如:代理服务器)缓存

l  public — 标记认证内容也可以被缓存,一般来说:经过HTTP认证才能访问的内容,输出是自动不可以缓存的;

l  private — 指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。

l  no-cache — 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。这对于需要确认认证应用很有用(可以和public结合使用),或者严格要求使用最新数据的应用(不惜牺牲使用缓存的所有好处);

l  no-store — 强制缓存在任何情况下都不要保留任何副本

l  must-revalidate — 告诉缓存必须遵循所有你给予副本的新鲜度的,HTTP允许缓存在某些特定情况下返回过期数据,指定了这个属性,你高速缓存,你希望严格的遵循你的规则。

l  proxy-revalidate — 和 must-revalidate类似,除了他只对缓存代理服务器起作用

l  min-fresh 指示客户机可以接收响应时间小于当前时间加上指定时间的响应。

l  max-stale 指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。 

可以在ajax返回结果中加缓存,以及一些请求加缓存,这个需要程序实现。

Last-Modified

在第一次请求时服务器会返回一个200状态以及响应正文,同时在响应头中会有Last-Modified 信息,例如:Last-Modified: Mon, 25 Jul 2011 02:01:46 GMT

在第二次请求该URL时浏览器会在请求头信息中发送If-Modified-Since 信息,例如:

If-Modified-Since: Wed, 20 Jul 201106:31:59 GMT,如果服务器资源没有发生变化则返回304状态,如果有变化则返回响应正文。

Etag

Etag是配合If-None-Match来使用的,在服务器响应头信息中加入Etag,如:

Etag W/"1795-1310539468000",在请求头信息中加入If-None-Match发送etag信息到服务器,如:If-None-Match         W/"1795-1310539468000",可以通过服务器配置来实现,也可以通过程序来实现。

 

对静态文件生成版本引用

封装成标签来统一生成html代码,基本思路是根据文件的名称(包括路径)当做key,文件的最后更新时间当做value存储在内存中,每次的html代码都从内存中获取版本信息来生成引用的html代码。

 

可以优化

1.        现有的static服务器缓存设置似乎有点问题,静态文件应该直接在客户端获取缓存,而不应该每次去服务器去校验返回304状态码。

                              

HTTP/1.0304 Not Modified

Date:Sun, 24 Jul 2011 15:49:13 GMT

Content-Type:application/x-javascript; charset=utf-8

Expires: Sun, 24 Jul 2011 16:49:06 GMT

Last-Modified: Tue, 14 Dec 2010 03:22:35 GMT

Cache-Control:max-age=3600

X-Via:1.0 shnh222:8106 (Cdn Cache Server V2.0)

Age:142178

Warning:113 proxy1.staff.woyo.com (squid/3.1.9) This cache hit is still fresh and morethan 1 day old, 110 squid/3.1.9 "Response is stale", 111 squid/3.1.9"Revalidation failed"

X-Cache:HIT from proxy1.staff.woyo.com

Via: 1.0proxy1.staff.woyo.com (squid/3.1.9)

Connection: keep-alive

可以看出设置应该在2011年7月24 16:49:06 过期,也就是说现在访问该缓存已经过期!

为什么是304状态呢?

因为在响应头信息中Last-Modified: Tue, 14 Dec 2010 03:22:35 GMT,而在请求头信息中有:If-Modified-SinceTue,14 Dec 2010 03:22:35 GMT,也就说客户端实际去访问了服务器,服务器检测到该文件并没有修改过所以返回304状态码。

         我们想要做到的是,一些js、css、img等静态文件信息直接在客户端缓存。

2.        在ajax以及页面的请求响应中加入Cache-Control 来控制缓存。

3.        Etag可以使用在静态文件也可以用在页面请求,静态文件可以直接nginx中配置,页面请求的需要程序来完成。

Nginx配置  http://mikewest.org/2008/11/generating-etags-for-static-content-using-nginx  

 

 

 

总结

1.        Last-Modified, Etag条件缓存控制参数,需要和服务器请求查看资源是否改变,可以减少资源的下载量,但是不会减少请求数。

2.        Expires,Cache-Control过期时间设置,同时设置时Cache-Control会覆盖Expires(只限于普通请求,如:链接点击跳转、用JS脚本打开新页面、使用iframe时),如果F5或者Ctrl+F5则忽略过期时间的设定。

3.        如果同时设置了过期时间和控制参数,在未过期时间内读取缓存不发起请求,过期后则发起请求,过期时间级别高于控制参数。

4.        no-cache在IE中有效,no-store在firefox中有效,一般同时设置2个,如:

Cache-Control: no-cache, no-store。

表1  Cache-Control可设置值

说明

max-age=xxx 

缓存的内容将在 xxx 秒后失效 , 这个选项只在  HTTP 1.1 可用 , 并如果和  Expires、Last-Modified 一起使用时 , 优先级较高

must-revalidation/

proxy-revalidation

如果缓存的内容失效,请求必须发送到服务器 / 代理以进行重新验证

no-store

所有内容都不会被缓存到缓存或 Internet 临时文件中

no-cache

所有内容都不会被缓存

private

内容只缓存到私有缓存中

public

所有内容都将被缓存

 

 

总结:

打开新窗口

如果指定 cache-control 的值为 private 、 no-cache 、 must-revalidate, 那么打开新窗口访问时都会重新访问服务器。而如果指定了 max-age 值 , 那么在此值内的时间里就不会重新访问服务器 , 例如: Cache-control: max-age=5 表示当访问此网页后的 5 秒内再次访问不会去服务器 

在地址栏回车

如果值为 private 或 must-revalidate, 则只有第一次访问时会访问服务器 , 以后就不再访问。如果值为 no-cache, 那么每次都会访问。如果值为 max-age,  则在过期之前不会重复访问。

按后退按扭

如果值为 private 、 must-revalidate 、 max-age, 则不会重访问 , 而如果为 no-cache, 则每次都重复访问

按刷新按扭

无论为何值 , 都会重复访问

HTTP协议(rfc2626)中文翻译(修订版) 三

缺省情况下,若请求方法、请求头域和响应状态码指明响应为可缓存的,则此响应就是可以缓存的。13.4节总结了可缓存性的这些缺省情况。下列缓存控制响应指令(Cache-Control response deirctives)允许源服务器覆盖缺省的响应可缓存性:

public

指明响应可被任何缓存保存,即便该响应通常是不可缓存的或只在非共享缓存里是可缓存的。(参见14.8节,关于Authorization头域的更多详述。)

private

指明响应消息的部分或所有部分是为一个用户准备的并且不得被共享缓存保存。可以使源服务器可以声明响应的特定部分来针对某一用户并且对其他用户的请求是无效的。一个私有(非共享)缓存可以缓存此响应。

注:词语“私有”的使用仅用来控制响应在何处可被缓存,并且不能保证消息内容的隐私。

no-cache

如果no-cache缓存控制指令没有指定一个field-name,那么一个缓存不能利用此响应在没有通过源服务器对它进行成功重验证的情况下去满足后续的请求。这允许源服务器去防止响应被缓存保存,即使此缓存已被设置可以返回陈旧响应给客户端。 

如果no-cache缓存控制指令指定一个或多个field-name,那么缓存可以利用此响应去满足后续的请求,但这要受限于对缓存的其它限制。然而,指定的filed-name必须不能在后续请求的响应里被发送如果此响应没有在源服务器那里得到成功重验证。这允许源服务器能防止缓存去重利用响应里的某些头域,但仍然允许缓存能保存响应剩余部分。

注意:大多数HTTP/1.0缓存将不能识别或遵循这个指令。
14.9.2什么能被缓存保存

no-store

no-store缓存控制指令的目的在于防止不经意地释放或保留敏感信息(比如存放在备份磁带的信息)。 no-store缓存控制指令应用于整个消息,并且可以在响应里或在请求里被发送。如果在请求里被发送,缓存不能保存此请求或此请求响应的任何部分。如果在响应里被发送,缓存不能保存此响应或保存此响应请求的任何部分。此缓存控制指令能应用于非共享缓存和共享缓存。“不能保存”在这个背景里的意思是指缓存不能有意地把信息保存在非易失性存储里,而且必须尽力去删除易失性存储上的信息当它转发完毕后。

即使当此指令在一个响应里时,用户也可能会显式地在缓存系统之外保存这个响应(例如,利用一个“另存为”对话框)的地方。历史缓冲(History buffers)(见13.13节)可能保存这个响应作为它们正常操作的一个部分。 

此指令的目的是为了满足某些用户声明的要求,还有就是为那些比较在意通过访问缓存数据结构而发生信息泄漏的作者提供方便。在一些情况下,利用此缓存控制指令可能会增强隐私,但是我们注意到它并不是在任何情况下都是可信任的或都能充分地保护隐私的。特别是,恶意的或被损坏的缓存可能不能识别到或遵循此指令,并且网络通信也容易随时受到窃听。
14.9.3对基本过期机制的改进

实体的过期时间可由源服务器利用“Expires”头域(参见14.21节)指定。 或者,也可以在响应里利用max-age缓存控制指令指定。当max-age缓存控制指令出现在一个已缓存的响应里时,如果此响应的当前年龄(current age,译注:见13.2.3节关于current age的定义)大于为那个资源的一个新请求时max-age里给定的年龄值(以秒),那么这个已缓存的响应是陈旧的(stale)。对在一个响应里应用max-age缓存控制指令意味着此响应是可缓存的(也就是说“公有的”)除非出现其它更具限制性的缓存控制指令于响应里。

若响应同时含有Expires头域和max-age缓存控制指令,那么max-age缓存控制指令应该覆盖Expires头域,即使Expires头域更具限制性。此规则允许源服务器可以为一给定响应来为一HTTP/1.1(或更迟)缓存提供一个比一HTTP/1.0缓存更长的过期时间(expiration time)。这个规则可能会很有用,如果某个HTTP/1.0缓存不恰当地计算了年龄(ages)或过期时间(expiration times),可能由于不同步的时钟。

许多HTTP/1.0缓存实现可能会把响应里小于或等于该响应里Date头域值的Expires头域值看成与“no-cache”缓存控制响应指令等效。如果一个HTTP/1.1缓存接收到这样一个响应,并且此响应没有包含一个Cache-Control头域,缓存应把此响应看成一个不可缓存的,这是为了保持和HTTP/1.0服务器兼容。 

注意:一个源服务器可能希望把一个相对较新的HTTP缓存控制特性,例如“private”缓存控制指令,用于一个存有不能理解此特性的旧的缓存的网络上。源服务器应该需要把新特性和响应里值小于或等于Date值的Expires头域联合起来,这样以便防止旧缓存不恰当地保存此响应。

s-maxage

如果一响应包含一s-maxage缓存控制指令,那么对于一共享缓存(不能对私有缓存)来说,s-maxage指定的值将会覆盖max-age缓存控制指令或Expires头域。s-maxage缓存控制指令照样意指proxy-revalidate缓存控制指令(见14.9.4节)的语义,也就是说,共享缓存在没有通过源服务器首先重验证这个已陈旧的缓存项时不能利用它来响应后续的请求。s-maxage缓存控制指令总是被私有缓存忽略。

注意:大多数不遵循此规范的老的缓存没有实现任何缓存控制指令。 一个源服务器如果希望利用一缓存控制指令去限制(但不能阻止)遵循HTTP/1.1的缓存去进行缓存处理,那么它可能会采用max-age控制指令去覆盖Expires头域,并且它会承认HTTP/1.1以前版本的缓存不会去观察max-age缓存控制指令。

其它缓存控制指令允许一个用户代理(user agent)去改变基本的过期机制。这些指令可能会被指定在请求里:

max-age 

表明客户端愿接受这样一个响应,此响应的年龄不大于客户端请求里max-age指定时间(以秒为单位)。除非max-stale缓存控制指令也包含在请求里,否则客户端是不能接收一个陈旧响应的。

min-fresh 

表明客户端愿接受一个这样的响应,其保鲜寿命不小于响应当前年龄(current age,见13.2.3节关于current_age的定义)与客户端请求里的min-fresh指定的时间之和(以秒为单位)。也就是说,客户端想要一个响应至少在min-fresh指定的时间内是保鲜的。

max-stale 

表明客户端愿接受已经过期的响应。 若客户端请求为max-age指定了一个值,则表明客户端愿意接受过期时间不超过在max-stale里指定秒数的响应。若max-stale没有赋值,则客户端愿接受任意年龄的陈旧响应。

由于max-stale缓存控制指令出现在请求里,或由于此缓存被设置成能覆盖响应的过期时间,导致缓存返回了一个陈旧响应,那么缓存必须把一个Warning头域放进这个陈旧响应里,此Warning头域里应该是110警告码(响应是陈旧的)。

一个缓存可以被设置为可以不需要验证就可以返回陈旧的响应,但这不应与任何关于缓存验证(例如,一个“must-revalidate”缓存控制指令)的“必须”等级的要求相冲突。

若新请求与缓存项都包含一个“max-age”缓存控制指令,那么取两个值的小者来为此请求决定缓存项的保鲜程度。 
14.9.4缓存重验证和加载控制(Cache Revalidation and Reload Controls)

有时,用户代理可能希望或出于需要,坚持要求某缓存通过源服务器去重验证其缓存项,或者要求其缓存从源服务器那里重新加载其缓存项。End-to-end重验证也许是有必要的,如果缓存或源服务器已过高估计已缓存的响应(cached response)的过期时间。End-to-end重新加载可能是必要的,如果缓存项由于某原因已经变得陈旧了。

End-to-end重验证可能被请求,当客户端没有本地缓存副本,此时我们称之为“未指定的end-to-end重验证(unspecified end-to-end revalidation)”,或者,当客户端存有本地缓存副本,此时我们称之为“指定的end-to-end重验证(specific end-to-end revalidation)”。

利用缓存控制请求指令,客户端能指定下面三种动作:

End-to-end reload (End-to-end重新加载)

请求包含“no-cache”缓存控制指令,或,为了兼容HTTP/1.0客户端,“Pragma: no-cache”缓存控制指令。头域名不能被包含在请求的no-cache缓存控制指令里。服务器不能利用一个缓存副本来响应这样一个请求。

Specific end-to-end revalidation(指定的end-to-end重验证)

请求包含一个“max-age=0”缓存控制指令,它强制每个途径源服务器的缓存必须通过下一缓存或服务器来重验证它所拥有的缓存项(如果有的话)。此初始请求包含一带有客户端当前验证器的缓存验证条件。

Unspecified end-to-end revalidation(未指定的end-to-end重验证)

请求包含一个“max-age=0”缓存控制指令,它强制每个途径源服务器的缓存必须通过下一缓存或服务器来重验证它所拥有的缓存项(如果有的话)。此初始请求没有包含一缓存验证条件;沿着路径上的第一个拥有此资源缓存项的缓存(如果有的话)在请求里包含一带有其缓存当前验证器的缓存验证条件。

max-age

当一个中间缓存被一个max-age=0的缓存控制指令强迫去重验证它所拥有的缓存项,并且客户端已经在请求里包含了其本身拥有的验证器,此验证器可能不同于当前缓存项里保存的验证器。在这种情况下,缓存应该在不影响语义透明性的情况下利用任一验证器去执行请求。

然而,验证器的选择可能会影响性能。最好的办法对中间缓存来说,就是当执行请求时利用它自己的验证器。如果服务器以304(没有改变)回复,那么此缓存能返回一个它自己现在已经验证了的副本给客户端同时以一200(OK)状态码。如果服务器以一新实体和一新缓存验证器来回复请求,那么此中间缓存会把返回的验证器同客户端请求里的验证器作比较,并利用强比较方法。如果客户端的验证器和源服务器的相等,那么此中间缓存器只是简单的返回304(没有改变)响应。否则,它返回一个新的实体并且状态码是200的响应。

如果一个请求包含一个no-cache缓存控制指令,那么它不应包含min-fresh,max-stale,或max-age缓存控制指令。

only-if-cache

在一些情况下,例如糟糕的网络连接,一客户端可能希望一缓存只返回缓存当前保存的响应,并且不需要缓存通过源服务器对其缓存项进行重新加载或重验证。如果这样作,客户端可能会包含一个only-if-cached缓存控制指令于请求里。如果缓存接收了这样的指令,那么缓存应利用缓存项(但必须满足请求的其它方面的限制)去响应,或以504(网关超时)状态码响应。然而,如果一组缓存作为一统一的具有良好内部连接性的系统来操作,那么这个请求可能会转发到缓存组的内部。

must-revalidate

由于一个缓存可能被设置去忽略服务器指定的过期时间,并且又由于一个客户端请求可能包含一个max-stale缓存控制指令(具有相似的作用),所以此协议同样包含一个让源服务器强迫缓存项被重验证的机制。当must-revalidate缓存控制指令出现在已被缓存接收的响应里时,那么此缓存不能利用此缓存项,如果在它变得陈旧并且没有通过源服务器对它进行重验证的情况下,去响应一个后续的请求。(也就是说,缓存必须每次进行end-to-end重验证,如果单独地基于源服务器的Expire或max-age值,已缓存的响应是陈旧的话)

must-revalidate缓存控制指令可以为某些协议特性提供可信赖性操作。在所有情况下,一个HTTP/1.1缓存必须遵循must-revalidate缓存控制指令;特别地,如果此缓存不能直接和源服务器通信,那么它必须产生一个504(网关超时)响应。

服务器应发送must-revalidate缓存控制指令,如果并且只有在服务器对实体的验证请求失败而导致不正确的操作时,例如一个不动声息的未执行的金融事务。接收端不能采取任何违反此缓存控制指令的自动的行为,并且不能自动地提供一个被验证无效的实体副本如果此副本通过源服务器重验证失败。

尽管这不被推荐,用户代理(user agent)如果在糟糕的网络连接限制下,可能会违反此缓存控制指令,但是,如果这样的话,它必须显式地警告用户这是一个未验证的响应。警告必须在每次未验证的访问时被提供,而且用户代理应需要用户显式地确认信息。

proxy-revalidate

proxy-revalidate缓存控制指令和must-revalidate缓存控制指令具有相同的语义,但它不能应用于非共享(non-shared)的用户代理缓存。它能被用于一已被授权请求的响应,去允许用户缓存能保存或者过后能返回此响应而不需要去重验证它(因为它已经被那个用户授权了一次),但是服务于多个用户的代理仍然需要每次去重验证它(为了保证每个用户已被授权)。注意这样的授权响应同样需要public缓存控制指令,这是为了允许响应能完全被缓存。
14.9.5 No-Transform缓存控制指令 

no-ransform

中间缓存(代理)的实现者们已发现转换某个实体主体的媒体类型转是很有用的。一个非透明代理可能,例如,会在不同图像格式之间进行转换,这是为了节约空间或在低速的连接上减少通信流量。

然而,当这些转换应用于某些应用的实体主体时,会引发严重操作问题。比如,医学图象应用程序,科学数据分析应用程序和利用end-to-end认证的应用程序都必须保证接收到的实体主体与原实体主体每一bit都是一致的。 

所以,如果消息包括了no-ransform缓存控制指令, 那么中间缓存或代理不能改变13.5.2节中列出的受限于no-transform缓存控制指令的头域。这意味着缓存或代理不能改变由这些头域指定的实体主体的任何方面(aspect),包括实体主体本身的值。 
14.9.6缓存控制扩展(Cache control Extendions)

Cache-Control头域能被扩展,可通过一个或多个cache-extension标记,每个标记可以被赋于一个值。信息扩展(这些扩展无须缓存行为的改变)可以不经改变其它缓存控制指令的语义而被添加。行为扩展是通过现有缓存控制指令的基本行为的修饰来实现的。 新缓存控制指令与标准缓存控制指令两者都被提供,这样,不理解新缓存控制指令的应用程序会缺省地采用标准缓存控制指令规定的行为,而那些能理解新指令的应用程序会将其看做是修改了标准缓存控制指令的要求。这样,缓存控制指令的扩展可以在无须改变基本协议的情况下就能够实现。

扩展机制依赖于一HTTP缓存,此缓存遵从所有本地HTTP版本缓存定义的缓存控制指令,遵从一定的扩展,并且会忽略所有它不能理解的缓存控制指令。

例如,考虑一个假设的名为“community”的新缓存响应控制指令,此指令被看成是对private缓存控制指令的修饰。我们定义此新缓存控制指令以表明:除共享缓存,任何被communit值命名的社区成员共享的缓存也可缓存此响应。例如,如果一个源服务器希望允许UCI社区里的成员在他们共享缓存里可以使用一私有响应,那么此源服务器应该包含:

Cache-Control: private, commuity="UCI" 

一个见到此头域的缓存将会正确执行,即使此缓存不能理解这个community缓存扩展,因为缓存同样能看到并且能理解private缓存控制指令所以这样能导致缺省的安全行为。

不能识别的缓存控制指令必须被忽略;我们认为不能被HTTP/1.1缓存识别的任一缓存控制指令会和标准缓存控制指令(或者响应的缺省缓存能力)联合在一起这样缓存行为会保持最小正确性即使缓存不理解此扩展。
14.10 Connection

Connection常用头域允许发送者指定某些专属于某特定连接的选项,并且Connection头域不能被代理(proxy)在以后的连接中传送。

Connection头域遵循如下语法:

Connection = “Connection” “:” 1#(connection-token)

connection-token = token

HTTP/1.1代理必须在转发消息之前解析Connection头域并且,为此头域中每一个connection-token,从消息中删除任何与connection-token里同名头域。 连接选项是由Connection头域中出现connection-token而指明的,而不是由任何相应的附加头域,因为附加头域可以不被发送如果对应的那个连接没有参数。

Connection头域里列出的消息头域不得包含end-to-end头域,例如Cache-Control头域。

HTTP/1.1定义了“close”连接选项,这是为了让发送者指明在完成响应后连接将被关闭。

例如 

Connection:close 

无论是出现在请求或响应的头域里都表明:在完成现有请求/响应后连接不应被视是“持续的(persistent)”(参见8.1节)。

不支持持久连接的HTTP/1.1应用程序必须在每一消息中都加上“close”连接选项。

接收到含有Connection头域的HTTP/1.0(或更低版本)消息的系统必须要为每一个connection-token去删除或忽略消息中与之同名的头域。这避免以前版本的HTTP/1.1代理错误转发这些头域。
14.11 Content-Encoding

“Content-Encoding”实体头域是对媒体类型的修饰。当此头域出现时,其值表明对实体主体采用了何种内容编码,从而可以知道采用何种解码机制以获取Content-Type头域中指出的媒体类型。Content-Encoding头域主要目的是可以在不丢失下层媒体类型的标识下对文档进行压缩。

Content-Encoding = "Content - Encoding" ":" 1#content-coding 

内容编码在3.5节里定义。下面是一个应用的例子:

Content-Encoding:gzip 

内容编码(content-coding)是请求URI指定实体的特性。通常,实体主体以内容编码(content-coding)的方式存储,然而只有在此实体主体被呈现给用户之前才能被解码。然而,非透明代理可能会把实体主体的内容编码(content-coding)改成接收端能理解的内容编码(content-coding),除非“no-transform”缓存控制指令出现在消息里。

如果实体的内容编码不是“identity”,那么此响应必须包含一个Content-Encoding实体头域(见14.11节)并且列出非dentity的内容编码。

若实体的内容编码(content-coding)是一不被源服务器接受的请求消息,则响应必须以415状态码响应(不支持的媒体类型)。

若实体采用多种编码,则内容编码必须在Content-Encdoing头域里列出,而且还必须按他们被编码的顺序列出。额外的关于编码参数的信息可以在其它实体头域里提供,这在此规范里没有定义。
14.12 Content-Language

Content-Language实体头域描述了实体面向用户的自然语言。请注意,这不一定等同于实体主体中用到的所有语言。

Content-Language = “Content-Language” “:” 1#language-tag

语言标签由3.10节定义。Content-Language头域的主要目的在于让用户根据自己喜爱的语言来识别和区分实体。这样,如果实体主体的内容是面向丹麦语言的用户,那么下面的头域是适合的:

Content-Language: da 

若未指明Content-Language头域,那么此内容缺省是对所有语言的用户都支持。这既可能意味着发送者认为实体主体的内容与任意自然语言无关,也可能是发送者不知道内容该针对哪种语言。

在Content-Language头域里可以为内容(content)列出多种语言。例如,同时用毛里土语和英语呈现“Treaty of Waitangi”就可以用下面表示:

Content-Language: mi,en 

然而,有多种语言呈现于实体中并不代表此实体一定是为多个国家语言的用户准备的。比如《初学拉丁文》之类的语言启蒙教程,显然是针对英语用户的。这里,合适的Content-Language头域里应只包括“en”。

Content-Language可应用于任意媒体类型(media type) -- 它不限于文本式的文档。
14.13 Content-Length

Content-Length实体头域用于指明发送给接收者实体主体(entity-bidy)的大小(以十进制的字节数表示),或是在使用HEAD方法时,指明实体主体本应在GET方法时发送实体主体的大小。

Content-Length = “Content-Length” “:” 1*DIGIT 

示例:

Content-Length: 3495 

除非被4.4节里规定的规则禁止,否则应用程序应该利用此头域指明消息主体(message-body)的传输长度。

任何大于或等于0的Content-Length均为有效值。如果一个Content-Length没有在消息里给定,4.4节描述了如何判断消息主体的长度。

请注意Content-Length头域的含义与MIME中的关于此头域的定义有很大的区别,MIME中,它在content-type类型为“message/external-body”的消息里是可选的。在HTTP中,在消息被传输之前,如果消息的长度能被确定,那么消息里应该包含Content-Length头域,除非不被4.4节里的规则允许。
14.14 Content-Location

Content-Location实体头域可用来为消息里的实体提供对应资源的位置,当此实体的访问位置独立于请求URI时。一服务器应该为响应实体的变量(variant,译注:见1.3节 术语)提供一个Content-Location头域;尤其是在资源有多个对应的实体时,并且这些实体拥有各自不同的位置,并且可以通过这些位置单独地访问到各个实体,这时服务器应该为一个特定的变量(variant)提供一个Content-Location头域。 

Content – Location = “Content-Location” “:” (absoluteURI | relativeURI)

Content-Location的值同样为实体定义了基URI(base URI)。

Content-Location的值并不能作为源请求URI(original requested URI)的替代物;它只能是陈述了请求时相应于特定实体的资源位置。将来的请求也许会用Content-Location里的URI作为请求URI,如果请求期望指定那个特定实体源。

如果一个实体含有一个Content-Location头域,并且此头域里的URI不同于获得此实体的URI,那么缓存不能认为此实体能被用于去响应基于那个Content-Location里URI的后续请求。然而,Content-Location能被用于区分同一请求资源的多个实体,这在13.6节里描述了。

若Content-Location拥有的是相对URI(relative URI),则此相对URI(relative URI)是相对于请求URI来解析的(Request-URI)。

PUT或POST请求中含有Content-Location头域是没有定义的;服务器可自由忽略它。 
14.15 Content-MD5

Content-MD5实体头域,正如RFC1864[23]里定义的一样,提供实体主体(entity-body)的MD5摘要(digest),为的是提供end-to-end消息完整性检测(MIC)。(注:一MIC有利于检测实体主体传输过程中的偶然性变动,但不一定能防范恶意攻击。)

Content-MD5 = "Content-MD5" ":" md5-digest 

MD5-digest=< 由RFC 1864 定义的base64的128位MD5摘要> 

Content-MD5头域可由源服务器或客户端产生,用作实体主体的完整性检验。只有源服务器或客户端可生成Content-MD5头域;不得由代理和网关生成,否则会有悖于其作为端到端完整性检验的价值。任何实体主体的接收者,包括代理和网关,都可以检查此头域里的摘要值与接收到的实体主体的摘要值是否相符。

MD5摘要的计算基于实体主体的内容,包括任何已应用的内容编码(content-coding),但不包括应用于消息主体的任何传输编码。若接收到的消息具有传输编码,那么传输编码必须在用Content-MD5值与接收到的实体相检测之前被解除。

这样做的结果是:摘要的计算是基于实体主体(entity-body)的字节的,就像一条命令:如果没有传输编码被应用,它们将会被发送。

HTTP 将RFC 1864拓宽到允许对MIME复合媒体类型(如multipart/*,message/rfc822)计算摘要,但这并不改变如前所述的摘要计算方法。

有一些关于这个的后果。复合媒体类型(composite types)的实体主体可能包含许多body-part,每一个body-part都有它自己的MIME和HTTP头域(包括Content-MD5,Content-Transfer-Encoding,和Content-Encoding头域),如果一个body-part有一个Content-Transfer-Encoding或Content-Encoding头域,那么应该认为此body-part的内容已被应用此编码,并且认为此body-part被包含于Content-MD5摘要里,就是说在应用编码之后。Transfer-Encoding头域不被允许出现在body-part里。

不可在计算或核对摘要之前就将任何其它换行转换为CRLF:实际传输的文本中使用的换行必须原封不动的参与摘要计算。

注:虽然HTTP的Content-MD5的定义和RFC 1864中关于MIME实体主体的完全一样, 但HTTP 实体主体在对Content-MD5的应用上仍然有几处与MIME实体主体有所区别。首先,HTTP不象MIME会用Content-Transfer-Encoding头域,而是会使用Transfer-Encoding和Content-Encoding头域。 其次,HTTP比MIME更多地使用二进制内容类型,所以这种情况要注意用于计算摘要的字节顺序是由那个类型所定义的传输字节顺序(transmission byte order)。最后,HTTP允许文本类传输时采用数种换行,而不只是规范的使用CRLF的的标准形式。
14.16 Content-Range

Content-Range实体头域与部分实体主体一起发送,用于指明部分实体主体在完整实体主体里哪部分被采用。 范围的单位(Range unit)在3.12节中定义。 

Content-Range = "Content-Range" ":" content-range-spec

content-range-spec = byte-content-range-spec

byte-content-range-spec = bytes-unit SP

byte-range-resp-spec "/"

( instance-length | "*" )

byte-range-resp-spec = (first-byte-pos "-" last-byte-pos)

| "*"

instance-length = 1*DIGIT

除非无法或很难判断,此头域应指明完整实体主体的总长度。星号“*”表示生成响应时的instance-length未知。

不像byte-ranges-specifier值(参见14.35.1节),byte-range-resp-spec必须只能指明一个范围,并且必须包含首字节和尾字节的绝对位置。

一个带有byte-range-resp-spec的byte-content-range-spec,如果它的last-byte-pos值小于first-byte-pos值,或它的instance-length值小于或等于它的last-byte-pos值,那么就说明是无效的。收到无效的byte-content-range-spec将被忽略,并且任何随其传输的内容都将被忽略。

响应时发送状态码416(请求的范围无法满足)的服务器应包含一个Content-Range头域,且里面的byte-range-resp-spec的值为“*”。instance-length指定当前选定资源的长度。状态码为206(部分内容)的响应不应该包含一个byte-range-resp-sepc为“*”的Content-Range头域。

假定实体共含1234字节,byte-content-range-spec值的例子如下:

. The first 500 bytes:

bytes 0-499/1234

. The second 500 bytes:

bytes 500-999/1234

. All except for the first 500 bytes:

bytes 500-1233/1234

. The last 500 bytes:

bytes 734-1233/1234

当HTTP消息里包含单个范围时(比如,对单个范围请求的响应,或对一组无缝相连的范围请求的响应),那么此内容必须跟随一个Content-Range头域,并且还应该包含一个Content-Length头域来表明实际被传输字节的数量。例如,

HTTP/1.1 206 Partial content

Date: Wed, 15 Nov 1995 06:25:24 GMT

Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT

Content-Range: bytes 21010-47021/47022 

Content-Length: 26012

Content-Type: image/gif

当HTTP报文包含多个范围时(比如,对多个无重叠范围请求的响应),它们会被当作多部分类型的消息来传送。基于为此目的多部分媒体类型为“multipart/byteranges”,它在附录19.2里介绍了。见19.6.3里关于兼容性的问题描述。

对单个范围请求的响应不能使用multipart/byteranges媒体类型。若对多个范围请求的响应结果为一单个范围,那么可以以一个multipart/byteranges媒体类型发送并且此媒体类型里只有一个部分(part)。一个客户端如果无法对multipart/byteranges消息解码,那么它不能在一请求中请求多个字节范围。

当客户端在一请求中申请多个字节范围时,服务器应按他们在请求中出现顺序的范围返回他们所指定的范围。

若服务器出于句法无效的原因忽略了byte-range-spec,它应把请求里无效的Range头域视为不存在。(正常情况下,这意味着返回一个包含完整实体的200响应。)

如果服务器接收到一请求,此请求包含一无法满足的Range请求头域(也即,所有byte-range-spec里的first-byte-pos值大于当前选择资源的长度),那么它将返回一个416响应(请求的范围无法满足)(参见10.4.17节)。

注: 客户端对无法满足Range请求头域不能指望服务器一定返回416(请求的范围无法满足)响应而非200(OK)的响应,因为不是所有服务器都能处理Range请求头域。
14.17 Content-Type

Content-Type实体头域指明发给接收者的实体主体的媒体类型,或在HEAD方法中指明若请求为GET时将发送的媒体类型。

Content-Type = "Content-Type" ":" media-type

媒体类型有3.7节定义。 此头域的示例如下:

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

7.2.1节提供了关于确定实体媒体类型方法的进一步论述。
14.18 Date

Date常用头域表明产生消息的日期和时间,它和RFC822中的orig-date语义一样。此头域值是一个在3.3.1里描述的HTTP-date;它必须用RFC1123[8]里的date格式发送。

Date="Date"":"HTTP-date 

举个例子

Date:Tue,15 Nov 1994 08:12:31GMT

源服务器在所有的响应中必须包括一个日期头域,除了下面这些情况:

1. 如果响应的状态代码是100(继续)或101(转换协议),那么响应根据服务器的需要可以包含一个Date头域。

2. 如果响应状态代码表达了服务器的错误,如500(内部服务器错误)或503(难以获得的服务),那么源服务器就不适合或不能去产生一个有效的日期。

3. 如果服务器没有时钟,不能提供合理的当前时间的近似值,这个响应没必要包括Date头域,但在这种情况下必须遵照 14.18.1节中的规则。

一个收到的消息如果没有Date头域的话就会被接收者加上一个,如果这条消息将要被接收者缓存或者将要通过一需要日期的网关。一个没有时钟的HTTP实现不能在没有重验证响应时去缓存(保存)此响应。一个HTTP缓存,特别是一个共享缓存,应该使用一种机制,例如NTP[28],让它的时钟与外界可靠的时钟保持同步。

客户端在包括实体主体(entity-body)的消息中应该包含一个Date头域,例如在PUT和POST请求里,即时这样做是可选的。一个没有时钟的客户端不能在请求中发送Date头域。

一个Date头域中的HTTP-date不应该是一个消息产生时刻之后的日期和时间。它应该表示与消息产生时的日期和时间的最近似值,除非没有办法产生一个合理的精确日期和时间。理论上说,日期应该是在实体(entity)产生之前的那一刻,实际上,日期是在不影响其语义值的情况下消息产生期间的任意时刻。
14.18.1没有时钟的源服务器运作

一些源服务器实现可能没有可得时钟。一个没有可得时钟的源服务器不能给一个响应指定Expires或Last-Modified头域值,除非通过一个具有可信赖时钟的系统或用户,把此值与此资源联系在一起。可以给Expires赋予一值,此值在服务器的配置时间之时或之前将被视为过去。(这允许响应提前过期而不需要为每个资源保存单独的Expires值)。
14.19 ETag

Etag响应头域提供了请求对应变量(variant)的当前实体标签。与实体标签一起使用的头域在14.24,14.26和14.44节里描述。实体标签可用于比较来自同一资源的不同实体。(参见13.3.3节)

Etag = "Etag" ":" entity-tag

例: 

ETag: "xyzzy" 

ETag: W/"xyzzy" 

ETag: "" 
14.20 Expect

Expect请求头域用于指明客户端需要的特定服务器行为。

Expect = "Expect" ":" 1#expectation

expectation = "100-continue" | expectation-extension

expectation-extension = token [ "=" ( token | quoted-string )

*expect-params ]

expect-params = ";" token [ "=" ( token | quoted-string ) ]

一个服务器如果不能理解或遵循一个请求里Expect头域的任何expectation值,那么它必须以合适的错误状态码响应。如果服务器不能满足任何expectation值,服务器必须以417(期望失败)状态码响应,或者如果服务器满足请求时遇到其它问题,服务器必须发送4xx状态码。

本头域为将来的扩展被定义成一个扩展的语法。若服务器接收到的请求含有它不支持的expectation-extension,那么它必须以417(期望失败)状态响应。

expectation值的比较对于未引用标记(unquoted token)(包括“100-contine”标记)是而言是不区分大小写的,对引用字符串(quoted-string)的expectation-extension而言是区分大小写的。

Expect机制是hop-by-hop的:即HTTP/1.1代理(proxy)必须返回417(期望失败)响应如果它接收了一个它不能满足的expectation。 然而,Expect请求头域本身是end-to-end头域;它必须要随请求一起转发。

许多旧版的HTTP/1.0和HTTP/1.1应用程序并不理解Expect头域。

参见8.2.3节中100(继续)状态的使用。 
14.21 Expires

Expires实体头域(entity-header)给出了在何时之后响应即被视为陈旧的。一个陈旧的缓存项不能被缓存(一个代理缓存或一个用户代理的缓存)返回给客户端,除非此缓存项被源服务器(或者被一个拥有实体的保鲜副本的中间缓存)验证。见13.2节关于过期模型的进一步的讨论。

Expires头域的出现并不意味着资源在Expire指定时间时、之前或之后将会改变或不存在。 

Expires头域里日期格式是绝对日期(absolute date)和时间,由3.3.1节中HTTP-date定义;它必须是RFC1123里的日期格式:

Expires="Expires " ":" HTTP-date 

使用示例为:

Expires: Thu, 01 Dec 1994 16:00:00 GMT

注:若响应包含一个Cache-Control头域,并且含有max-age缓存控制指令(参见14.9.3节),则此指令覆盖Expires头域。

HTTP/1.1客户端和缓存必须把其它无效的日期格式,特别是包含“0”的日期格式看成是过去的时间(也就是说,“已经过期”)。

为了将响应标为“已经过期”,源服务器必须把Expires头域里的日期设为与Date头域值相等。(参见13.2.4节里关于过期计算的规则。)

为标记响应为“永不过期”,源服务器必须把Expires头域里的日期设为晚于响应发送时间一年左右。HTTP/1.1服务器不应发送超过将来一年的过期日期。

除非另外被Cache-Control头域(见14.9节)指明,否则如果存在Expires头域且头域里的日期值为某响应(可能缺省是不可缓存的)将来时间,那么就表明此响应是可缓存的。 
14.22 From

From请求头域,如果有的话,应该包含用户代理当前操作用户的email地址。这个地址应该是机器可用的地址,这被RFC 822 [9]里的“mailbox”定义的同时也在RFC 1123 [8]里作了修订:

From = "From" ":" mailbox 

例如:

From: webmaster@w3.org 

From头域可以被用于记录日志和作为识别无效或不期望请求的来源。他不应该被用作访问保护的不可靠方法。这个头域的解释是:此请求是代表所指定人执行,此人应该承担这个方法执行的责任。特别的,机器人代理(robot agents)应该包含这个头域,这样此人应该对运行此机器人代理程序负责,并且应该能被联系上如果在接收端出现问题的话。

此头域里的网络email地址是可以和发出请求的网络主机(host)不同。例如,当一个请求被通过一代理(proxy)时,源作者的地址应被使用。

客户端在没有用户的允许时是不应发出From头域的,因为它可能和用户的个人隐私或他们站点的安全策略(security policy)相冲突。强烈建议在任何一请求之前,用户能取消,授权,和修改这个头域的值。
14.23 Host

Host请求头域指明了请求资源的网络主机和端口号,这可以从用户或相关资源给定的源URI获得(通常是一个HTTP URL,在3.2.2节描述)。Host头域值必须代表源服务器或网关(由那个源URL指定)的命名权限(naming authority)。这允许源服务器或网关去区分有内在歧义的URLS,例如,拥有一个IP地址对应有多个主机名服务器,它的根“/”URL。 

Host = "Host" ":" host [ ":" port ] ; 3.2.2节

一个“host”如果没有跟随的端口信息,那么就采用是请求服务的的默认端口(例如,对一个HTTP URL来说,就是80端口)。例如,一个对源服务器“http://www.w3.org/pub/WWW/”的请求,可以用下面来表示:

GET /pub/WWW/HTTP/1.1

Host: www.w3.org

一个客户端必须在所有HTTP/1.1请求消息里包含一个Host头域。如果请求URI没有包含请求服务的网络主机名,那么Host头域必须给一个空值。一个HTTP/1.1代理必须确保任何它转发的请求消息里必须包含一个正确的Host头域,用于指定代理请求服务。所有基于网络的HTTP/1.1服务器必须响应400(坏请求)状态码,如果请求消息里缺少Host头域。

见5.2和19.6.1.1节里有针对Host头域的其他要求。
14.24 If-Match

If-Match请求头域是用来让方法成为条件方法。如果一个客户端已经从一个资源获得一个或多个实体(entity),那么它可以通过在If-Match头域里包含相应的实体标签(entity tag)来验证实体是否就是服务器当前实体。实体标签(entity tag)在3.11节里定义。这个特性使更新缓存信息只需要一个很小的事务开销。当更新请求时,它照样被用于防止对资源错误版本的不经意修改。作为一种特殊情况,“*”匹配资源的当前任何实体。 

If-Match = "If-Match" ":" ( "*" | 1#entity-tag )

如果If-Match头域里任何一个实体标签假设与一个相似GET请求(没有If-Match头域)返回响应里实体的实体标签相匹配,或者如果给出“*”并且请求资源的当前实体存在,那么服务器可以执行请求方法就好像If-Match头域不存在一样。

服务器必须用强比较方法(见13.3.3)来比较If-Match里的实体标签(entity tag)。

如果没有一个实体标签匹配,或者给出了“*”但服务器上没有当前的实体,那么服务器不能执行此请求的方法,并且返回412响应(先决条件失败)。这种行为是很有用的,特别是在当客户端希望防止一更新方法(updating method)(例如PUT方法)去修改此客户端上次获取但现已改变的资源时, 

如果请求假设在没有If-Match头域的情况下导致了除2XX或412以外的其他状态码响应,那么If-Match头域必须被接收端忽略。

“If-Match: *” 的含义是:此方法将被执行,如果源服务器(或缓存,很可能使用Vary机制,见14.44节)选择的表现形式(representation)存在的话,但是如果此表现形式不存在,那么此方法不能被执行。

如果一个请求想要更新一个资源(例如PUT)那么它可以包含一个If-Match头域来指明:当相应于If-Match值(一个实体标签)的实体不再是那个资源的表现形式时,此请求方法不能被采用。这允许用户表明:如果那个资源已经改变了而他们不知道的话,他们不希望请求成功。

例如:

If-Match: "xyzzy" 

If-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" 

If-Match: * 

既有If-Match头域又有If-None-Match或If-Modified-Since头域的请求的结果在本规范没有定义。
14.25 If-Modified-Since

If-Modified-Since请求头域被用来让方法成为条件方法:如果请求变量(variant)自从此头域里指定的时间之后没有改变,那么服务器不应该返回实体;而是应该以304(没有改变)状态码进行响应,同时返回的消息不需要消息主体(message-body)。

If-Modified-Since = "If-Modified-Since" ":" HTTP-date 

一个例子是:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT 

如果一个GET请求方法含有If-Modified-Since头域但无Range头域,那么此方法请求的实体只有请求里If-Modified-Since头域中指定日期之后被改变才能被服务器返回。决定这个算法包括下列情况:

a)如果请求假设会导致除状态200之外的任何其它状态码,或者如果If-Modified-Since日期是无效的,那么响应就和正常的GET请求的响应完全一样。比服务器当前时间晚的日期是无效的。

b)如果自从一个有效的If-Modified-Since日期以来,变量已经被修改了,那么服务器应该返回一个响应同正常GET请求一样。

c)如果自从一个有效的If-Modified-Since日期以来,变量没有被修改,那么服务器应该返回一个304(没有改变)响应。

这种特征的目的是以一个最小的事务开销来更新缓存信息。

注意:Range请求头域改变了If-Modified-Since的含义;详细信息见14.35。

注意:If-Modified-Since的时间是由服务器解析的,它的时钟可能和客户端的不同步。

注意:当处理一个If-Modified-Since头域的时候,一些服务器使用精确的日期比较方法,而不是小于(less-than)比较方法,来决定是否发送304(没有改变)响应。当为缓存验证而发送一个If-Modified-Since头域的时候,为了得到最好的结果,客户端被建议尽可能地去利用以前Last-Modified头域里被接收的日期字符串。 

注意:如果客户端,对同一请求,在If-Modified-Since头域中使用任意日期代替Last-Modified头域里得到的日期,那么客户端应该知道这个日期应该能被服务器理解。由于客户端和服务器之间时间编码的不同,客户端应该考虑时钟不同步和舍入的问题。如果在客户端第一次请求时与后来请求里头域If-Modified-Since指定的日期之间,文档发生改变,这就可能会出现竞争条件,还有,如果If-Modified-Since从客户端得到的日期没有得到服务器时钟的矫正,就有可能出现时钟偏差等问题的。客户端和服务器时间的偏差最有可能是由于网络的延迟造成的。

既有If-Modified-Since头域又有If-Match或If-Unmodified-Since头域的请求的结果在本规范没有定义。
14.26 If-None-Match

If-None-Match头域被用于一个方法使之成为条件的。一个客户端如果拥有一个或多个从某资源获得的实体,那么它能验证在这些实体中有不存在于服务器当前实体中的实体,这通过在If-None-Match头域里包含这些实体相关的实体标签(entity tag)来达到此目的。这个特性允许通过一个最小事务开销来更新缓存信息。它同样被用于防止一个更新方法(如,PUT)不经意的改变一个客户端认为不存在但事实却存在的资源。

作为特殊情况,头域值“*”匹配资源的任何当前实体。

If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

如果If-None-Match头域里的任何实体标签(entity tag)假设与一个相似的GET请求(假设没有If-None-Match头域)返回实体的实体标签相匹配,或者,如果“*”被给出并且服务器关于那个资源的任何当前实体存在,那么服务器不能执行此请求方法,除非资源的修改日期和请求里If-Modified-Since头域(假设有的话)里提供的日期匹配失败(译注:匹配失败说明资源改变了)。换言之,如果请求方法是GET或HEAD,那么服务器应以304(没有改变)来响应,并且包含匹配实体的相关缓存头域(特别是Etag) 。对于所有其它方法,服务器必须以412(先决条件失败)状态码响应。

13.3节说明了如何判断两实体标签是否匹配。弱比较方法只能用于GET或HEAD请求。

如果If-None-Match头域里没有实体标签匹配,那么服务器可以执行此请求方法就像If-None-Match头域不存在一样,但是必须忽略请求里的任何If-Modified-Since头域。也就是说,如果没有实体标签匹配 ,那么服务器不能返回304(没有改变)响应。

如果假设在没有If-None-Match头域存在的情况下,请求会导致除2xx及304状态码之外响应,那么If-None-Match头域必须被忽略。(见13.3.4节关于假如同时存在If-Modified-Since和If-None-Match头域时服务器的行为的讨论)

“If-None-Match: *”的意思是:如果被源服务器(或被缓存,可能利用Vary机制,见14.44节)选择的表现形式(representation)存在的话,请求方法不能被执行,然而,如果表现形式不存在的话,请求方法是能被执行的。这个特性可以防止在多个PUT操作中的竞争。

例: 

If-None-Match: "xyzzy" 

If-None-Match: W/"xyzzy" 

If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" 

If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz" 

If-None-Match: * 

如果一个请求含有If-None-Match头域,还含有一个If-Match或If-Unmodified-Since头域的话,此请求的指向结果在此规范里没有定义。
14.27 If-Range

如果客户端在其缓存中有一实体的部分副本,并希望其整个缓存项是及时更新的,那么客户端可以在一条件GET(conditional GET)(利用了If-Unmodified-Since和If-Match头域两者或其中之一)请求里利用Range请求头域。然而,如果由于实体被改变而使条件失败,那么客户端可能会发出第二次请求从而去获得整个当前实体主体(entity-body)。

If-Range头域允许客户端使第二次请求短路(short-circuit)。说的通俗一点,这意味着:如果实体没有改变,发送我想要的部分;如果实体改变了,那就把整个新实体发过来。

If-Range = “if-Range” “:”( entity-tag | HTTP-date)

若客户端没有一实体标签(entity tag),但有一个最后修改日期(Last-Modified date),它可以在If-Range头域里利用此日期。(服务器通过检查一两个字符即可区分合法HTTP-date与任意形式的entity-tag。)If-Range头域只应该与一Range头域一起使用,并且必须被忽略如果请求不包含一个Range头域或者如果服务器不支持子范围(sub-range)操作。

如果If-Range头域里给定的实体标签匹配服务器上当前实体的实体标签(entity tag),那么服务器应该提供此实体的指定范围,并利用206(部分内容)响应。如果实体标签(entity tag)不匹配,那么服务器应该返回整个实体,并利用200(ok)响应。
14.28 If-Unmodified-Since

If-Unmodified-Since请求头域被用于一个方法使之成为条件方法。如果请求资源自从此头域指定时间开始之后没有改变,那么服务器应该执行此请求就像If-Unmodified-Since头域不存在一样。

如果请求变量(variant,译注:见术语)在此头域指定时间后以后已经改变,那么服务器不能执行此请求,并且必须返回412(前提条件失败)状态码。

If-Unmodified-Since = "If-Unmodified-Since" ":" HTTP-日期

此域的应用实例: 

If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT

如果请求正常情况下(即假设在没有If-Unmodified-Since头域的情况下)导致任何非2xx或412状态码,那么If-Unmodified-Since头域将会忽略。

如果此头域中指定的日期无效,那么此头域会被忽略。

在请求里有If-Unmodified-Since头域并且有If-None-Match或者If-Modified-Since头域中的一个,这种请求的处理结果在此规范中没有被定义。
14.29 Last-Modified

Last-Modified实体头域(entity-header)指定了变量(variant)被源服务器所确信的最后修改的日期和时间。

Last-Modified = “Last-Modified” “:” HTTP-date

应用示例如下:

Last-Modified : Tue, 15 Nov 1994 12:45:26 GMT

此头域的确切含义取决于源服务器的实现和源资源(original resource)的性质。 对文件而言,它可能仅仅指示文件上次修改的时间。对于包含动态部分的实体而言,它可能是组成其各个部分中最后修改时间最近的那个部分。对数据库网关而言,它可能是记录的最新修改时间戳。对虚拟对象来说,它可能是最后内部状态改变的时间。

源服务器不能发送一个迟于消息产生时间的Last-Modified日期。假如资源最后修改日期可能指示将来的某个时间,那么服务器应该用消息产生的时间替换那个日期。

源服务器获得实体Last-Modified值应尽量靠近服务器产生响应的Date值。这允许接收者对实体修改时间作出准确的估计,特别是如果实体的改变时间接近响应产生的时间。

HTTP/1.1服务器应该尽可能地发送Last-Modified头域。
14.30 Location

Location响应头域被用于为了完成请求或识别一个新资源,使接收者能重定向于Location指明的URI而不是请求URI。对于201(Created)响应而言,Location是请求建立新资源的位置。对于3xx响应而言,Location应被指定服务器为自动重定向资源所喜爱的URI。Location头域值由一个绝对URI组成。

Location = “Location” “:” absoluteURI

一个例子如下:

Location : http://www.w3.org/pub/WWW/People.html

注: Content-Location头域(14.14节)不同于Location头域,Content-Location头域指定了请求里封装实体的源位置。有可能一个响应即包含location也包含Content-Location头域。在13.10节里有关于一些方法的要求。
14.31 Max-Forwards

Max-Forwards请求头域为TRACE(9.8节)和OPTIONS(9.2节)提供一种机制去限制转发请求的代理或网关的数量。当客户端尝试去跟踪一个好像陷入失败或陷入循环的请求链时,这是非常有帮助的。

Max-Forwards = “Max – Forwards” “:” 1*DIGIT

Max-Forwards值是十进制的整数,它指定了请求消息可以剩余转发的次数。

对于一个TRACE或OPTIONS请求,如果包含一个Max-Forwards头域,那么接收此请求的代理或网关必须能在转发(forwarding)此请求之前检查和更新Max-Forwards头域值。如果接收的值为0,那么接收者不能转发此请求;而是,它必须作为最后的接收者响应。如果接收的Max-Forwards值比0大,那么此转发的消息必须包含一个更新了的Max-Forwards头域,更新的值是在接收时的值上减去1。

对本规范定义的所有其它方法以及任何没有明确作为方法定义部分的扩展方法的请求里,Max-Forwards头域可能会被忽略。
14.32 Pragma 

Pragma常用头域被用于包含特定执行指令,这些指令可能被应用于请求/响应链中任何接收者。从协议的观点来看,pragma指令指定的行为是可选的;然而,一些系统可能要求行为必须满足指令的要求。

Pragma = “Pragma” “:” 1#pragma-directive

pragma-directive =”no-cache” | extension-pragma

extension-pragma =token [ “=” ( token | quoted-string) ]

当no-cache指令出现在请求消息中,应用程序应该转发(forward)此请求到源服务器,即使它拥有此请求响应的缓存副本。pragma指令和no-cache缓存控制指令(见14.9)有相同的语义,并且它是为同HTTP/1.0向后兼容而被定义。当一个no-cache请求发送给一个不遵循HTTP/1.1的服务器时,客户端应该既包含pragma指令也包含no-cache缓存控制指令。

pragma指令必须能穿过代理和网关应用程序,不管对于那些应用程序有没有意义。因为这些指令可能对请求/响应链上的所有接受者有用。不可能为一个特定的接收者定义一个pragma;然而,任何对接收者不相关的pragma指令都应该被接收者忽略。

HTTP/1.1缓存应该把“Pragma:no-cache”当作好像客户端发送了“cache-control:no-cache”。在HTTP中不会有新的pragma指令会被定义。
14.33 Proxy-Authenticate

Proxy-Authenticate响应头域必须被包含在407响应(代理授权)里。此头域值由一个challenge和parameters组成,challenge指明了授权模式,而parameters应用于请求URI的代理。

Proxy-Authenticate = "Proxy-Authenticate" ":" 1#challenge 

关于HTTP访问授权过程的描述在“HTTP Authentication:Basic and Digest Access Authentication”[43]中介绍了。不像WWW-Authenticate头域,Proxy-Authenticate头域只能应用于当前连接,并且不应该传递给下游(downstrem)客户端。然而,一个中间代理可能需要从请求下游客户端而获得它自己的证书(credentials),这在一些情况下就好像代理正在转发Proxy-Authenticate头域一样。
14.34 Proxy-Authorization

Proxy-Authorization请求头域允许客户端让一代理能给客户端自己(或客户端的用户)授权。Proxy-Authorization头域值由包含用户代理(为代理和/或请求资源域)的授权信息的证书组成。

Proxy-Authorization = “Proxy-Authorization” “:” credentials

HTTP访问授权过程在“HTTP Authentication: Basic and Digest Access Authentication”[43]中描述。不像Authorization头域,Proxy-Authorization头域只能应用于下一个期望利用Proxy-Authenticate头域授权的外向(outbound)代理。。
14.35 Range
14.35.1字节范围 (Byte Ranges)

既然所有的HTTP实体都以字节序列形式的HTTP消息表示,那么字节范围的概念对任何HTTP实体都是有意义的.(不过并不是所有的客户和服务器都需要支持字节范围操作.。)

HTTP里的字节范围应用于实体主体的字节序列(不必和消息主体一样)。

字节范围操作可能会在一个实体里指定一个字节范围或多个字节范围。

ranges-specifier = byte-ranges-specifier 

byte-ranges-specifier = bytes-unit "=" byte-range-set 

byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec )

byte-range-spec = first-byte-pos "-" [last-byte-pos] 

first-byte-pos = 1*DIGIT 

last-byte-pos = 1*DIGIT 

byte-range-spec里的first-byte-pos值给出了一个范围里第一个字节的偏移量.。last-byte-pos值给出了这个范围里最后一个字节的偏移量;也就是说,确定的字节位置必须在实体的范围之内。字节偏移是以0为基准(译注:0代表第一个字节,1代表第二个字节)。

如果存在last-byte-pos值,那么它一定大于或等于那个byte-range-spec里的first-byte-pos,否则byte-range-spec在句法上是非法的。接收者接收到包括一个或多个无效的byte-range-spec值的byte-range-set时,它必须忽略包含那个byte-range-set的头域.。

如果last-byte-pos值不存在,或者大于或等于实体主体的当前长度,则认为last-byte-pos等于当前实体主体长度减一。

通过选择last-byte-pos,客户能够限制获得实体的字节数量而不需要知道实体的大小。 

suffix-byte-range-spec = “-“ suffix-length

suffix-length = 1*DIGIT

suffix-byte-range-spec用来表示实体主体的后缀,其长度由suffix-length值给出.。(也就是说,这种形式规定了实体正文的最后N个字节。)如果实体短于指定的suffix-length,则使用整个实体主体。

如果一个句法正确的byte-range-set至少包括一个这样的byte-range-spec,它的first-byte-pos比实体主体的当前长度要小,或至少包括一个suffix-length非零的 suffix-byte-range-spec,那么byte-range-set是可以满足的,否则是不可满足的。如果byte-range-set不能满足,那么服务器应该返回一个416响应(请求范围不能满足)。否则,服务器应该返回一个206响应(部分内容)

byte-ranges-specifier(字节-范围-说明符)值的例子(假定实体主体的长度为10000): 

-- 第一个500字节(字节偏移量0-499,包括0和499): bytes=0-499 

-- 第二个500字节(字节偏移量500-999,包括500和999): bytes=500-999 

-- 最后500字节(字节偏移量9500-9999,包括9500和9999): bytes=-500 或 bytes=9500- 

-- 仅仅第一个和最后一个字节(字节0和9999): bytes=0-0,-1 

-- 关于第二个500字节(字节偏移量500-999,包括500和999)的几种合法但不规范的叙述: 

bytes=500-600,601-999 

bytes=500-700,601-999 
14.35.2范围请求(Range Retrieval Requests)

使用条件或无条件GET方法可以请求实体的一个或多个字节范围,而不是整个实体,这利用Range请求头域,请求返回的结果就是Range头域指示的请求资源实体的范围。

Range = "Range" ":" ranges-specifier 

服务器可以忽略Range头域。然而,.HTTP/1.1源服务器和中间缓存应该尽可能支持字节范围,因为Range支持从部分失败传输中有效地恢复,并且支持从大的实体中有效地获取部分内容。

如果服务器支持Range头域,并且指定的范围或多个范围对实体来说是适合的:

1. 如果在无条件GET请求里出现Range头域,那么这将会改变没有Range头域时的GET请求返回的结果。换句话说,返回的状态码不是200(ok)而是206(部分响应)。

2. 如果在条件GET(请求里利用了If-Modified-Since和If-None-Match中任意一个或两者,或者利用了If-Unmodified-Since和If-Match中的任意一个或两者)请求里出现Range头域,那么这将改变返回的结果,如果GET请求假设在没有Range头域时被服务器成功响应并且条件为真。但如果条件为假,它不会影响304(没有改变)响应被返回。

某些情形下,除了使用Range头域外,可能还要同时使用If-Range头域(见14.27节)。

如果支持范围请求的代理接收了一个范围请求,并转发(forward)请求到内向(inbound)服务器,并且接收到了一个完整实体,那么它只应该返回给客户请求的范围。代理将接收的整个响应存储到它的缓存里如果此响应满足缓存分配策略。
14.36 Referer

Referer请求头域允许客户端,为了让服务器受益,指定请求URI来源的资源URI。(Referer头域的Referer本应该写成Referrer,出现了笔误)。Referer请求头域允许服务器为了个人兴趣,记录日志,优化缓存等来产生回退链接列表。它照样允许服务器为维护而跟踪过时或写错的链接。Referer头域不能被发送如果请求URI从一个没有自身URI的资源获得,例如用户从键盘输入。

Referer = "Referer" ":" ( absoluteURI | relativeURI )

例如: 

Referer: http://www.w3.org/hypertext/DataSources/Overview.html 

如果Referer头域的域值是相对URI,那么它将被解析为相对于请求URI。URI不能包含一个片段(fragment)。见15.1.3关于安全的考虑。
14.37 Retry-After

Retry-After响应头域能被用于一个503(服务不可得)响应,服务器用它来向请求端指明服务不可得的时长。此头域可能被用于3xx(重定向)响应,服务器用它来(如web浏览器)指明用户代理再次提交已重定向请求之前的最小等待时间。Retry-After头域值可能是HTTP-date或者也可能是一个响应时间后的十进制整数秒。

Retry-After = “Retry-After” “:” ( HTTP-date | delta-seconds )

下面是它的两个例子

Retry-After: Fri,31 Dec 1999 23:59:59 GMT

Retry-After:120

在后一例子中,延迟时间是2分钟。
14.38 Server

Server响应头域包含了源服务器用于处理请求的软件信息。 此域可包含多个产品标记(3.8节),以及鉴别服务器与其他重要子产品的注释。产品标记按它们的重要性来排列,并鉴别应用程序。

Server = “Server” 

例:

服务器:CERN/3.0 libwww/2.17 

若响应是通过代理转发的,则代理程序不得修改Server响应头域。作为替代,它应该包含一个Via头域(在14.45节里描述)。

注:揭示特定的软件版本可能会使服务器易于受到那些针对已知安全漏洞的软件的攻击。 建议服务器实现者将此域作为可设置项。
14.39 TE

TE请求头域指明客户端可以接受哪些传输编码(transfer-coding)的响应,和是否愿意接受块(chunked)传输编码响应的尾部(trailer)(译注:TE头域和Accept-Encoding头域与Content-Encoding头域很相似,但TE应用于传输编码(transfer coding),而Content-Encoding应用于内容编码(content coding,见3.5节))。 TE请求头域的值可能由包含关键字“trailers” 和/或用逗号分隔的扩展传输编码名(扩展传输编码名可能会携带可选的接受参数的列表)(在3.6节描述)组成。

TE = "TE" ":" #( t-codings )

t-codings = "trailers" | ( transfer-extension [ accept-params ] )

如果出现关键字“trailers”,那么它指明客户端愿意接受(chunked)传输编码响应的尾部(trailer)。 此关键字为传输编码(transfer-coding)值而保留,但它本身不代表一种传输编码。

举例:

TE: deflate 

TE: 

TE: trailers, deflate;q=0.5 

TE请求头域仅适用于立即连接。所以无论何时,只要在HTTP/1.1消息中存在TE头域,连接头域(Connection header filed)(参见14.10节)中就必须指明。

通过TE头域,服务器能利用下述规则来测试传输编码(transfer-coding)是否是可被客户端接受的:

1.块(chunked)传输编码总是可以接受的。如果在TE头域里出现关键字“trailers”,那么客户端指明它愿意代表自己或任意下游(downstream)客户端去接受块(chunked)传输编码响应里的尾部(trailer)。这意味着,如果“trailers”给定,客户端正在声明所有下游(downstream)客户端愿意接收块(chunked)传输编码响应里的尾部(trailer),或声明它愿意代表下游接收端去尝试缓存响应。

注意:HTTP/1.1并没有定义任何方法去限制块传输编码响应的大小,这是为了方便客户端能缓存整个响应。

2.只要是出现在TE头域里的传输编码都是可被请求端接受的,除非此传输编码跟随的qvalue值为0(根据3.9节中定义,qvalue为0表明是“不可接受的”(not acceptable)))

3.如果在TE头域里有指明多个传输编码是可接受的,那么传输编码(transfer-coding)的qvalue值最大的是最容易被被接受的。块传输编码的qvalue值为1。

如果TE头域值是空的或者TE头域没有出现在消息里,那么服务器只能认为块(chunked)传输编码的响应是请求端可以接受的。没有传输编码的消息总是可接受的。
14.40 Trailer

Trailer常用头域值指明了以块(chunked)传输编码的消息里尾部(trailer)用到的头域。

Trailer = "Trailer" ":" 1#field-name 

一个HTTP/1.1消息会包含一个Trailer头域,如果消息利用了块(chunked)传输编码并且编码里的尾部(trailer)不为空。这样做是为了使接收端知道块(chunked)传输编码响应消息尾部(trailer)有哪些头域。

如果具有块传输编码的消息,但没有Trailer头域存在,则此消息的尾部(trailer)将不能包括任何头域。3.6.1节展示了块传输编码的尾部(trailer)的利用限制。

Trailer头域中指示的消息头域不能包括下面的头域:

.Transfer-Encoding

.Content-Length

.Trailer 


14.41 Transfer-Encoding

传输译码(Transfer-Encoding)常用头域指示了消息主体(message body)的编码转换,这是为了实现在接收端和发送端之间的安全数据传输。它不同于内容编码(content-coding),传输代码是消息的属性,而不是实体(entity)的属性。

Transfer-Encoding = "Transfer-Encoding" ":" 1#transfer-coding 

传输编码(transfer-coding)在3.6节中被定义了。一个例子是:

Transfer-Encoding: chunked 

如果一个实体应用了多种传输编码,传输编码(transfer-coding)必须以应用的顺序列出。传输编码(transfer-coding)可能会提供编码参数(译注:看传输编码的定义,3.6节),这些编码参数额外的信息可能会被其它实体头域(entity-header)提供,但这并没有在规范里定义。



许多老的HTTP/1.1应用程序不能理解传输译码(Transfer-Encoding)头域。
14.42 Upgrade

Upgrade常用头域允许客户端指定它所支持的附加通信协议,并且可能会使用如果服务器觉得可以进行协议切换。服务器必须利用Upgrade头域于一个101(切换协议)响应里,用来指明哪个协议被切换了。

Upgrade = “Upgrade” “:” 1#product

例如,

Upgrade: HTTP/2.0,SHTTP/1.3, IRC/6.9, RTA/x11

Upgrade头域的目的是为了提供一个从HTTP/1.1到其它不兼容协议的简单迁移机制。这通过允许客户端告诉服务器客户端期望利用另一种协议,例如主版本号更高的最新HTTP协议,即使当前请求仍然使用HTTP/1.1。这能降低不兼容协议之间迁移的难度,只需要客户端以一个更普遍被支持协议发起一个请求,同时告诉服务器客户端想利用“更好的”协议如果可以的话(“更好的”由服务器决定,可能根据方法和/或请求资源的性质决定)。

Upgrade头域只能应用于应用程序层(application –layer)协议之间的切换,应用程序层协议在传输层(transport-layer)连接之上。Upgrade头域并不意味着协议一定要改变;并且服务器接受和使用是可选的。在协议改变后应用程序层(apllication-layer)的通信能力和性质,完全依赖于新协议的选择,尽管在改变协议后的第一个动作必须是对初始HTTP请求(包含Upgrade头域)的响应。

Upgrade头域只能应用于立即连接(immediate connection)。因此,upgrade关键字必须被提供在Connection头域里(见14.10节),只要Upgrade头域呈现在HTTP/1.1消息里。

Upgrade头域不能被用来指定切换到一个不同连接的协议。为这个目的,使用301,302,303重定向响应更合适。

这个规范定义了本协议的名字为“HTTP”,它在3.1节的HTTP版本规则中定义的超文本传输协议家族中被使用。任何一个标记都可被用来做协议名字,然而,只有当客户端和服务器认为这个名字对应同一协议才有用。
14.43 User-Agent

User-Agent请求头域包含关于发起请求的用户代理的信息。这是为了统计,跟踪协议违反的情况,和为了识别用户代理从而为特定用户代理自动定制响应。用户代理应该包含User-Agent头域在请求中。此头域包含多个识别代理和子产品的产品标记(见3.8节)和解释。通常,为了识别应用程序,产品标记按重要性排列。

User-Agent = "User-Agent" ":" 1*( product | comment )

例子: 

User-Agent: CERN-LineMode/2.15 libwww/2.17b3 
14.44 Vary

Vary响应头域值指定了一些请求头域,全部去决定某缓存是否被允许去利用此响应(并且此响应仍然保鲜)去回复后续请求而不需要重验证(revalidation)。对于不可缓存或已陈旧的响应,Vary头域值用于告诉用户代理(user agent)选择表现形式(reprentation)的标准。一个Vary头域值是“*”意味着缓存不能根据后续请求的请求头域来决定此响应是合适的表现形式。见13.6节关于缓存如何利用Vary头域。

Vary = "Vary" ":" ( "*" | 1#field-name )

一个HTTP/1.1的服务器应该包含一个Vary头域于任何可缓存的受限于服务器驱动协商的响应里。这样做是允许缓存恰当去理解关于那个资源的将来请求,并通知用户代理关于那个资源的协商出现。一个服务器可能包含一个Vary头域于一个不可缓存的受限于服务器驱动协商的响应里,因为这样做可能为用户代理提供有用的关于响应变化的维度的信息。

一个Vary头域值由域名(filed-name)组成,响应的表现形式是基于Vary头域里列举的请求头域来选择的。一个缓存可能会假设为将来请求进行相同的选择,如果Vary头域例举了相同的域名,但必须是此响应在此期间是保鲜的。

Vary头域里的域名并不是局限于本规范里定义的标准请求头域。域名是大小写不敏感的。

Vary域值为“*”指明不受限于请求头域的非特指参数(例如,客户端的网络地址)作用于响应表现形式中进行选择 。“*”值不能被代理产生;它可能只能被源服务器产生。
14.45 Via

Via常用头域必须被网关(gateways)和代理(proxies)使用,用来指明在用户代理和服务器之间关于请求的中间协议和接收者,和在源服务器和客户端之间关于响应的中间协议和接收者。它和RFC822[9]里的“Received”头域相似,并且它用于跟踪消息的转发,避免请求循环,和指定沿着请求/响应链的所有发送者的协议能力。

Via = "Via" ":" 1#( received-protocol received-by [ comment ] )

received-protocol = [ protocol-name "/" ] protocol-version 

protocol-name = token 

protocol-version = token 

received-by = ( host [ ":" port ] ) | pseudonym 

pseudonym = token 

received-protocol指出沿着请求/响应链每一段的服务器或客户端所接收消息的协议版本。protocol-version被追加于Via头域值后面,当消息被转发时。

只要协议是HTTP,那么protocol-name是可有可无的。received-by头域通常是接收的转发服务器的host(主机)和可选的port(端口)号,或接收的转发客户端的host(主机)和可选的port(端口)号。然而,如果真实host(主机)被看作是信息敏感的,那么此主机可能会被别名代替。如果port(端口号)没有被给定,那么它可能被假设为received-protocol的缺省port(端口)号。

Via头域里如果有多个域值,则每个值分别代表一个已经转发消息的代理或网关。每一个接收者必须把它的信息追加到最后,所以最后的结果是按照转发应用程序的顺序来的。

comment(注释)可能被用于Via头域是为了指定接收者代理或网关的软件,这个好比User-Agent和Server头域。然而,Via头域里所有的comment是可选的(译注:可有可无的),并且可以被接收者在转发消息之前移去。

例如,有一个请求消息来自于一个HTTP/1.0用户代理,被发送到代号为“fred”的内部代理,此内部代理利用HTTP/1.1协议转发此请求给一个站点为nowhere.com的公共代理,而此公共代理为了完成此请求通过把它转发到站点为“www.ics.uci,edu”的源服务器。被“www.ics.uci.edu”站点接收后的请求这时可能有下面的Via头域:

Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)

被用作通向网络防火墙的入口的代理和网关在缺省情况下不应该转发host(主机)的名字和端口到防火墙区域里。如果这些信息显示地指定要被传送,那么就应该被传送。如果此信息显示地指定不能被传送,那么任何穿过防火墙而被接收的host(主机)应该用一个合适的别名替换。

为了隐藏组织结构的内部结构需要,一个代理(proxy)可能会在一个Via头域中把相同received-protocal值的项合成一个项。例如,

Via: 1.0 ricky, 1.1 ethel, 1.1 fred, 1.0 lucy

将被折叠成

Via: 1.0 ricky, 1.1 mertz, 1.0 lucy

应用程序不应该合并多个项,除非他们都在相同组织的控制下并且host(主机)已经被别名代替了。应用程序不能合并不同received-protocaol值的项。
14.46 Warning

Warning常用头域被用于携带额外关于消息状态或消息转换的信息,而这些信息是不能在消息里反应出来的。这些信息通常被用于去警告由于缓存操作或消息主体转换带来的透明性(semantic transparency)的缺失。

Warning头域被用于响应里,这里有如下语法:

Warning = "Warning" ":" 1#warning-value 

warning-value = warn-code SP warn-agent SP warn-text 

[SP warn-date] 

warn-code = 3DIGIT 

warn-agent = ( host [ ":" port ] ) | pseudonym 

; the name or pseudonym of the server adding 

; the Warning header, for use in debugging 

warn-text = quoted-string 

warn-date = <"> HTTP-date <"> 

一个响应可能携带多个Warning头域。

warn-text必须使用对于接收响应的用户来说尽可能理解的自然语言和字符集。找到用户自能理解的自然语言和字符集,必须基于任何可能的知识,如缓存或用户的位置,请求里的Accept-Language头域,响应里的Content-Language头域,等等。缺省语言是英语,缺省字符集是ISO-8859-1。

如果字符集不是ISO-8859-1,那么它必须利用RFC2047里描述的来在warn-text里进行编码。

Warning头域能被应用于任何消息,然而,一些warn-codes是特定于缓存的,并且只能被应用于响应消息。新的Warning头域应添加到任何已存Warning头域的后面。缓存不能删除任何它接收到的消息里的Warning头域。然而,如果一缓存成功验证一缓存项,那么它应移除任何以前依附于那个缓存项的Warning头域除了特定警告码(Warning codes)的Warning头域。然后,它必须添加这个验证响应里的任何Warning头域。换句话说,Warning头域是依附于最近相关响应的Warning头域。

当多个Warning头域被附加于一个响应里,那么用户代理应该通知用户尽可能多的警告,并且以它们呈现在响应里的顺序。如果用户代理不能通知用户所有的警告,那么用户代理应该按照下面的规则:

- 前面的响应里的警告优于后面响应的警告

- 用户偏爱的字符集的警告优于其它字符集的警告,但这除了warn-codes和warn-agents一致的情况。

产生多个Warning头域的系统应该时刻记住利用用户代理行为来安排警告。

关于警告的缓存行为的要求在13.1.2里描述。

下面是当前定义的warn-codes,每一个warn-code都有一个建议性的以英语表示的warn-text,和它的意思的描述。

110 Response is stale

无论何时当返回响应是陈旧的时候,必须被包含。

111 Revalidation failed

如果一个缓存因为尝试去重验证响应失败而返回一个陈旧的响应(由于不能到达服务器),必须被包含。

112 Disconnected operation

如果缓存在一段时间被有意地断开连接,应该被包含。

113 Heuristic expiration

如果缓存探索性地选择了一个保鲜寿命大于24小时并且响应的年龄大于24小时时,必须被包含。

199 Miscellaneous warning

警告文本可能包含任意信息呈现给用户。除了呈现给用户警告,接收警告的系统不能采取任何自动行为。

214 Transformation applied

如果一个中间缓存或代理采用任何对响应的内容编码(content-coding)(在Content-Encoding头域里指定)或媒体类型(media-type)(在Content-Type头域里指定)的改变变,或响应的实体主体(entity-body)的改变,那么此响应码必须被中间缓存或代理添加,除非此警告码(warning code)已经在响应里出现。

299 Miscellaneous persistent warning

警告文本应该包含任意呈现给用户的任意信息。接收警告的系统不能采取任何自动行为。

如果一个实现在一个消息里发送多个版本是HTTP/1.0或更早的HTTP协议版本的Warning头域,那么发送者必须包含一个和响应日期(date)相等的warn-date到每一个Warning头域值中。

如果一个实现收到一条warning-value里包含一个warn-date的消息,并且那个warn-date不同于响应里的Date值,那么warning-value必须在保存,转发,或利用消息之前从消息里删除。(这回防止本地缓存去缓存Warning头域的恶果。)如果所有warning-value因为这个原因而被删除,Warning头域必须也要被删除。
14.47 WWW-Authenticate

WWW-Authenticate响应头域必须包含在401(没有被授权)响应消息中。此域值至少应该包含一个callenge,此callenge指明授权模式(schemes)和适用于请求URI的参数。

WWW-Authenticate =“WWW-Authenticate” “:” 1#challenge 

HTTP访问授权过程在“HTTP Authentication: Basic and Digest Access Authentication”[43]里描述。用户代理被建议特别小心去解析WWW-Authenticate头域值,当此头域值包含多个challenge,或如果多个WWW-Authenticate头域被提供且challenge的内容能包含逗号分隔的授权参数的时候。
15.安全考虑 (Security Consideration)

这一部分是用来提醒程序开发人员,信息提供者,和用户关于HTTP/1.1安全方面的限制。讨论并不包含对被披露问题的明确的解决办法,然而,它却对减少安全风险提供了一些建议。
15.1 个人信息 (Personal Information)

HTTP的客户端经常要对大量的个人信息保密(例如用户的名字,域,邮件地址,口令,密匙等。),并且应当非常小心地防止这些信息无意识地通过HTTP协议泄露到其他的资源。我们非常强烈地建议应该给用户提供一个方便的界面来控制这种信息的传播,并且设计者和实现者在这方面应该特别注意。历史告诉我们在这方面的错误经常引起严重的安全和/或者隐私问题,并导致对设计或实现者的公司产生非常不利的影响。 
15.1.1服务器日志信息的滥用 (Abuse of Server Log Information)

服务器是用来保存用来指定用户读模型或感兴趣主题的请求的。这些信息通常显然是需保密的,并且它的使用在某些国家被法律保护。利用HTTP协议提供数据的人们必须保证在这些数据被许可的情况下分发。
15.1.2敏感信息的传输 (Transfer of Sensitive Inforamtion)

就像任何数据传输协议一样,HTTP不能调整传输数据的内容,也没有任何经验方法在任意给定请求的背景里去判断特定信息的敏感性。因此,应用程序应该尽可能为此信息提供者提供对此信息的控制。在此背景里,有四个头域需要提出来,这四个头域是:Server,Via,Referer 和From。

揭露服务器特定软件版本信息可能会使服务器的机器更容易受到通过软件安全漏洞来进行攻击的攻击。实现者应该使Server头域成为可设置的选项。

用作穿过网络防火墙入口的代理应该特别小心防火墙后可以辨别主机信息的头域信息被传输。特别是,代理应移除在防火墙之后产生的任何Via头域。

Referer头域允许被学习的读模式和反向链接的跟踪。虽然它非常有用,但也会被滥用如果用户细节没有从包含在Referer头域里信息里分离开来。即使当个人信息已经被移除了,Referer头域也可能指定私有文档的URI(不能被公开)。

From头域里的信息可能会和用户的私有兴趣或他们站点的安全策略相冲突,因此From头域不应被传输在用户没有能使此头域的内容失效、有效和更改的情况下。用户必须能在用户的喜爱或应用程序的缺省设置范围内设置此头域的内容。

我们建议,尽管不需要,给用户提供一个方便的开关界面来使发送From和Referer头域有效或失效。

User-Agent(14.4节)或Server(14.38节)头域有时候能被用来去判断一个特定的客户端或服务器是否存在安全漏洞。不幸的是,同样的信息经常被用于其它有价值的目的,因为HTTP当前没有更好的机制。 
15.1.3 URI中敏感信息的编码(Encoding Sensitive Information in URI’s)

因为一个链接的源可能是私有信息或者可能揭露其它私有信息源,所以强烈建议用户能选择是否需要发送Referer头域。例如,浏览器客户端可能为了开放/匿名方式提供一个触发开关,此开关可能使Referer头域和From头域信息的发送有效/无效。

如果参考页面在一个安全的协议上传输,客户端不应该包含一个Referer头域在一个非安全HTTP请求里。

利用HTTP协议的服务作者不应该利用基于窗体GET提交敏感数据,因为这个能引起数据在请求URI里被编码。许多已存在的服务,代理,和用户代理将在对第三方可见的地方记录请求URI。服务器能利用基于窗体POST提交来取代基于窗体GET提交。
15.1.4连接到Accept头域的隐私问题

Accept请求头域能揭露用户的信息给所有被访问的服务器。Accept-Language头域能揭露用户的私有信息,因为能理解特定语言的人经常被认为就是某个特定种族里的成员。提供选项在每次请求里去设置Accept-Language头域的用户代理被强烈鼓励让设置过程应包含一个让用户知道自己隐私可能被会泄漏的消息。

一种限制隐私丢失的方法可能是缺省为用户代理去遗漏Accept-Language头域的发送,并且询问用户是否给开始给服务器发送Accept-Language头域,如果用户代理通过查看任何由服务器产生的Vary响应头域时发现这个发送能提高服务的质量。

每一个请求里的用户可配置的接受头域(accept header fields),特别是如果这些接受头域(accept header fileds)包含质量值,那么应该被服务器用作相对信赖和长久的用户标识符(user identifiers)。这样的用户标识符将会允许内容提供者进行点击跟踪以及允许合作内容提供者匹配跨服务器点击跟踪或者形成单个用户窗体提交。注意对于许多并不在代理后面的用户,运行用户代理的主机的网络地址也将作为长久用户的标识符。在代理被用作增强隐私的环境里,用户代理应保守地提供接受(accept)头域配置选项给终端用户上。作为一种高度隐私的方式,用户代理可能在接力的(relayed)的请求里的过滤接受头域。提供高度可配置性的用户代理应警告用户会有隐私的泄漏。
15.2 基于文件和路径名称的攻击 

HTTP的源服务器的实现应该限制HTTP请求返回的文档应是服务器管理员有意图的文档。如果HTTP服务器要把HTTP URIs翻译成文件系统的调用,那么服务器必须小心去对待提供给HTTP客户端的文件传输。例如,UNIX,微软Windows,和其他操作系统都利用“..”去指示当前的父目录。对于这样一个系统,一HTTP服务器不允许任何这样的构造(construct)在请求URI里,如果这个构造能在通过HTTP服务器访问之外能访问这个资源。同样的,用作对服务器内部引用的文件(如访问控制文件,配置文件,脚本代码)必须受到保护而不让其被不合适的获取,因为他们可能包含敏感的信息。经验告诉我们一个在HTTP服务器实现里的一个小小的错误会带来安全风险。
15.3 DNS欺骗

使用HTTP的客户端严重依赖于域名服务,因此这会导致基于IP和DNS名称的不关联的攻击。客户端需要小心关注IP地址/DNS名称关联的持久合法性。

特别是,HTTP客户端为了确认IP地址/DNS名称关联性,应该依赖于客户端自己的的名称解析器,而不应依赖缓存以前主机(host)名称查找(host name lookups)结果。许多平台在恰当的时候可在本地缓存主机名称查找(host name lookups),并且他们应被配置为可这样做。然而,只有当被名称服务器报告的TTL(Time To Live)信息指明被缓存的信息仍然有用时,才可以缓存查找(lookups)。 

如果HTTP客户端为了提高性能去缓存主机名称查找(host name lookups)的结果,那么他必须观察被DNS报告的TTL信息。

如果HTTP客户端不能看到这条规则,那么,当以前访问的IP地址改变时,他们就会被欺骗。因为网络地址的改变变得很平常,所以这种形式的攻击在不断增加。看到这个规则能减少潜在的安全攻击的可能性。

此要求同样能改进客户端负载均衡(load-balancing)行为,因为重复的服务器能利用同一个DNS名称,此要求能降低用户在访问利用策略(strategy)的站点中的体验失败。
15.4 Location头域和欺骗

如果单个的服务器支持互不信任的多个组织,那么它必须检查响应(在据称的组织的控制下产生)里Location和Content-Location头域值,以确信这些头域不会使它们没有权限的资源无效。
15.5 Content-Disposition的问题

RFC 1806 [35],在HTTP中经常使用的Content-Disposition(见19.5.1节)头域就源于此文档,有许多非常认真的安全考虑在此文档里说明。Content-Disposition并不是HTTP标准版本中的一部分,但自从它被广泛应用以来,我们正在证明它对使用者的价值和风险。详细资料见RFC 2183 [49](对RFC 1806的升级)。 
15.6 授权证书和空闲客户端

现有的HTTP客户端和用户代理通常会不明确地保留授权信息。HTTP/1.1并没有为服务器提供一个方法让服务器去指导客户端丢弃这些缓存的证书(credentials)。这是一个重大缺陷,此缺陷需要扩展HTTP协议来解决。在某些情形下,缓存证书会干涉应用程序的安全模型,这些情形包含但不局限于:

? 这样的客户端。此客户端空闲已到达一定时间,服务器可能希望再次使客户端让用户出示证书。 

? 这样的应用程序。此应用程序包括了一个会话中断指令(例如在一页上有“退出”或者“提交”的按钮),根据此指令,服务器端“知道”不需要更多理为客户端保留证书。

这是作为当前独立研究的。有很多解决这个问题的社区,并且我们鼓励在屏幕保护程序、空闲超时、和其他能减轻安全问题的方法里利用密码保护。特别是,能缓存证书的用户代理被鼓励去提供一个容易的访问控制机制,让在用户控制下丢弃缓存的证书。
15.7 代理和缓存 (Proxies and Caching)

本质上说,HTTP代理是中间人(men-in-the-middle),并且存在中间人攻击(man-in-the-middle attacks)危险。系统(代理运行于其上)的缺陷能导致严重的安全和隐私问题。代理拥有对相关安全信息、用户和组织的个人信息、和属于用户和内容提供者的专有信息的访问权限。一个有缺陷的代理,或一个没有考虑安全性和隐私性的代理可能会被委托用来攻击。

代理操作者应该保护代理运行其上的系统,正如他们保护任何包含或传输敏感信息的系统一样。特别是,代理上收集的日志信息经常包含较高的个人敏感信息,和/或关于组织的信息。日志信息应该被小心的保护,并且要合适地开发利用。(见15.1.1)节。

代理的设计者应当考虑到设计和编码判定所涉及到的隐私和安全问题,以及他们提供给代理操作人员配置选项(尤其是缺省配置)所牵涉到的隐私和安全问题。

代理的用户需要知道他们自比运行代理的操作员更不值得信赖;HTTP协议自身不能解决这个问题。

在合适的时候,对密码学的正确应用,可能会保护广泛的安全和隐私攻击。密码学的讨论不在本协议文档的范围内。
15.7.1关于代理的服务攻击的拒绝

代理是存在的。代理很难被保护。关于此研究正在进行。
16 感谢(Acknowledgment)

这份规范大量使用了扩展BNF和David为RFC 822 [9]定义的常用结构。同样的,它继续使用了很多Nathaniel Borenestein和Ned Freed为MIME [7]提供的定义。我们希望在此规范里他们的结论有助于减少过去在HTTP和互联网邮件消息格式关系上的混淆。

HTTP协议在这几年已经有了相当的发展。它受益于大量积极的开发人员的社区--许多人已经通过www-talk邮件列表参与进来--并且通常就是那个社区对HTTP和万维网的成功作了重大贡献。 Marc Andreessen, Robert Cailliau, Daniel W. Connolly, Bob Denny, John Franks, Jean-Francois Groff , Phillip M. Hallam-Baker, Hakon W. Lie, Ari Luotonen, Rob McCool, Lou Montulli, Dave Raggett, Tony Sanders, 和 Marc VanHeyningen因为他们在定义协议早期方面的贡献应该得到特别的赞誉。

这篇文档从所有那些参加HTTP-WG的人员的注释中获得了很大的益处。除了已经提到的那些人以外,下列人士对这个规范做出了贡献:

Gary Adams Ross Patterson 

Harald Tveit Alvestrand Albert Lunde 

Keith Ball John C. Mallery 

Brian Behlendorf Jean-Philippe Martin-Flatin 

Paul Burchard Mitra 

Maurizio Codogno David Morris 

Mike Cowlishaw Gavin Nicol 

Roman Czyborra Bill Perry 

Michael A. Dolan Jeffrey Perry 

David J. Fiander Scott Powers 

Alan Freier Owen Rees 

Marc Hedlund Luigi Rizzo 

Greg Herlihy David Robinson 

Koen Holtman Marc Salomon 

Alex Hopmann Rich Salz 

Bob Jernigan Allan M. Schiffman 

Shel Kaphan Jim Seidman 

Rohit Khare Chuck Shotton 

John Klensin Eric W. Sink 

Martijn Koster Simon E. Spero 

Alexei Kosut Richard N. Taylor 

David M. Kristol Robert S. Thau 

Daniel LaLiberte Bill (BearHeart) Weinman 

Ben Laurie Francois Yergeau 

Paul J. Leach Mary Ellen Zurko 

Daniel DuBois Josh Cohen 

缓存设计的许多内容和介绍应归于以下人士的建议和注释:Shel Kaphan, Paul Leach, Koen Holtman, David Morris, 和 Larry Masinter。

大部分规范的范围是基于Ari Luotonen和John Franks早期做的工作,以及从Steve Zilles另外加入的内容。

感谢Palo Alto的"cave men"。你们知道你们是谁。

Jim Gettys(这篇文档现在的编者)特别希望感谢Roy Fielding,这篇文档以前的编者,连同John Klensin, Jeff Mogul, Paul Leach, Dave Kristol, Koen Holtman, John Franks, Josh Cohen, Alex Hopmann, Scott Lawrence, 和Larry Masinter一起感谢他们的帮助。还要特别感谢Jeff Mogul和Scott Lawrence对“MUST/MAY/ SHOULD”使用的检查。

Apache组,Anselm Baird-Smith,Jigsaw的作者,和Henrik Frystyk在早期实现了RFC 2068,我们希望感谢他们发现了许多这篇文档正尝试纠正的问题。
19 附录 
19.1 互联网媒体类型message/http和application/http

这篇文档除了定义HTTP/1.1协议外,同时还被作为互联网媒体类型“message/http”和“application/http”的规范。此类型用于封装一个HTTP请求消息或响应消息,这假设此类型遵循MIME对 所有“消息”类型关于行长度和编码的限制。application/http类型可以用来封装一个或者更多HTTP请求或响应信息(非混合的)的管线(pipeline)。下列是在IANA[17]注册的。

媒体类型名称: message 

媒体子类型名称: http 

必须参数: 无

可选参数: 版本,信息类型

版本:封装信息的HTTP版本号(例如,"1.1")。如果不存在,版本可以从消息的第一行确定。

信息类型:信息类型--"请求"或者"响应"。如果不存在,类型可以从报文的第一行确定。 

编码考虑:只有"7bit","8bit",或者"二进制"是允许的。

安全考虑:无 

媒体类型名称: application 

媒体子类型名称: http 

必须参数: 无

可选参数: 版本,信息类型

版本:封装信息的HTTP版本号(例如,"1.1")。如果不存在,版本可以从报文的第一行确定。

信息类型:信息类型--"request"或者"response"。如果不存在,类型可以从报文的第一行确定。 

编码考虑:用这种类型封装的HTTP信息是"二进制"的格式;当通过E-mail传递的时候一种合适的内容传输编码是必须的。

安全考虑:无 
19.2 互联网媒体类型multipart/byteranges

当一个HTTP 206(部分内容)响应信息包含多个范围的内容(请求响应的内容有多个非重叠的范围),这些是作为一个多部分消息主体来被传送的。这种用途的媒体类型被称作"multipart/byteranges"。

multipart/byteranges媒体类型包括两个或者更多的部分,每一个都有自己Content-type和Content-Range头域。必需的分界参数(boundary parameter)指定分界字符串,此分界字符串用来隔离每一部分。

媒体类型名称: multipart 

媒体子类型名称: byteranges 

必须参数: boundary 

可选参数: 无

编码考虑:只有"7bit","8bit",或者"二进制"是允许的。

安全考虑:无 

例如:

HTTP/1.1 206 Partial Content 

Date: Wed, 15 Nov 1995 06:25:24 GMT 

Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT 

Content-type:multipart/byteranges;boundary=THIS_STRING_SEPARATES 

--THIS_STRING_SEPARATES 

Content-type: application/pdf 

Content-range: bytes 500-999/8000 

...第一部分... 

--THIS_STRING_SEPARATES 

Content-type: application/pdf 

Content-range: bytes 7000-7999/8000 

...第二部分

--THIS_STRING_SEPARATES-- 

注意:

1)在实体(entity)中,在第一个分界字符串之前可以有多余的CRLFs。 

2)虽然RFC 2046 [40]允许分界字符串加引号,但是一些现有的实现会不正确的处理分界字符串 

3)许多浏览器和服务器是按照字节范围标准的早期草案关于使用multipart/x-byteranges媒体类型来进行编码的的,这个草案不总是完全和HTTP/1.1中描述的版本兼容。 
19.3 放松的应用程序 (Tolerent Applications)

虽然这篇文档列出了HTTP/1.1消息所必须的元素,但是并不是所有的应用程序都能正确地实现。因此我们建议运行程序可以容忍偏差只要这些偏差能被无歧义的理解。

客户端应该放松地解析Status-Line(状态行);服务器也应该放松地解析Request-Line(请求行)。特别的,他们应该可以接受头域之间任何数量的SP或HT字符,即使协议规定只有一个SP。

消息头域的行终结符是CRLF。然而,当解析这样的头域时,我们建议应用程序能识别单一LF作为行终结符并能忽略CR。

实体主体(entity-body)的字符集应该被标记为应用于实体主体字符编码的最小公分母,并且期望不对实体进行标记要优于对实体标记为US-ASCII或ISO-8859-1。见3.7.1和3.4.1。

对关于日期分析和编码的要求的额外规则以及其它对日期编码的潜在问题包含:

? HTTP/1.1客户端和缓存应该假定一个似乎是50多年以后的RFC-850日期实际上是过去的(这有助于解决"2000年"问题)。

? 一个HTTP/1.1的实现可以内部地表示一个比正确日期值更早的已解析后的Expires日期,但是一定不要(MUST NOT)内部地表示一个比正确日期值更迟的已解析过的Expires日期。

? 所有过期日期相关的计算必须用GMT时间。本地时区一定不能(MUST NOT)影响年龄或过期时间的计算。

? 如果一个HTTP头域不正确的携带了一个非GMT时间区的日期值,那么必须利用最保守的可能转换把此日期值转换成GMT时间值。 
19.4 HTTP实体和RFC 2045实体之间的区别

HTTP/1.1使用了许多Internet Mail(RFC 822 [9])和Multipurpose Internet Mail Extensions(MIME [7])里定义的结构,去允许实体以多种表现形式和扩展机制去传输。然而,RFC2045讨论邮件,并且HTTP有许多不同于RFC2045里描述的特征。这些不同被小心地挑选出来优化二进制连接的性能,为了允许使用新的媒体类型有更大的灵活性,为了使时间比较变得容易,和为了承认一些早期HTTP服务器和客户端的实效。

本附录描述了HTTP协议不同于RFC 2045的特殊区域。在严格的MIME环境中的代理和网关应该意识到这些不同并且在必要的时候要提供合适地转换。从MIME环境到HTTP的代理和网关也需要意识到这些不同因为一些转换可能是需要的。 
19.4.1 MIME版本(MIME-Version)

HTTP不是一个遵守MIME的协议。然而HTTP/1.1消息可以包含一个单独的MIME-Version常用头域用来指出什么样的MIME协议版本被用于去构造消息。利用MIME-Version头域指明完全遵循MIME协议的消息(在RFC2045[7])。代理/网关要保证完全遵守MIME协议当把HTTP消息输出到严格MIME环境的时候。

MIME-Version = "MIME-Version" ":" 1*DIGIT "." 1*DIGIT 

在HTTP/1.1用的缺省值是MIME1.0版本。然而,HTTP/1.1消息的解析和语义是由本文档而不是MIME规范定义的。 
19.4.2转换到规范化形式 (Conversion to Canoical Form)

RFC 2045 [7]要求一互联网邮件实体在被传输之前要被转换成一个规范化的形式,这在RFC2049[48]里第四章里描述的。本文档的3.7.1节描述了当用HTTP协议传输时允许使用的“text”子媒体类型的形式。RFC2046要求类型为“text”的内容要用CRLF表示为换行符,以及在换行符外禁止使用CR或LF。

RFC 2046需要像在“text”类型的内容里一样,用CRLF表示行间隔符并禁止在行间隔符序列以外使用CR或者LF。HTTP允许CRLF,单个CR,和单个LF来表示一个换行符在一个文本内容消息中。

在可能的地方,从HTTP到MIME严格环境的代理或网关应该把RFC2049里描述的text媒体类型里所有换行符转换成RFC2049里CRLF的规范形式。然而,注意这可能在Content-Encoding出现的时候,以及HTTP允许利用一些没有利用13和10代表CR和LF的字符集时候都会变得复杂。

实现者应该注意转换将会破坏任何应用于源内容(original content)的密码校验和,除非源内容已经是规范化形式。因此,对任何在HTTP中使用校验和的内容被建议要表示为规范化形式。 
19.4.3日期格式的转换 (Conversion of Date Formate)

为了简化日期比较的过程,HTTP/1.1使用了一个限制的日期格式(3.3.1节)。其它协议的代理和网关应该保证任何消息里出现的Date头域应该遵循HTTP/1.1规定的格式,如果有必要需要重写此日期。 
19.4.4 Content-Encoding头域介绍 (Introduction of Content-Encoding)

RFC 2045不包含任何等价于HTTP/1.1里Content-Encoding头域的概念。因为这个头域作为媒体类型(media type)的修饰,从HTTP协议到MIME遵守协议的代理和网关在转发消息之前必须既能改变Content-Type头域的值,也能解码实体主体(entity-body).。(一些为互联网邮件类型的Content-Type的实验性应用有使用一个媒体类型参数“; conversions=<content-coding>”去执行等价于Content-Encoding的功能。然而,此参数并不是RFC2045的部分)
19.4.5没有Content-Transfer-Encoding头域

HTTP不使用RFC 2045里的Content-Transfer-Encoding(CTE)头域。从使用MIME协议到HTTP的代理和网关在把响应消息发送给HTTP客户端之前必须删除任何非等价(non-identity,译注:identity编码,表示没有进行任何编码)CTE("quoted-printable"或"base64")编码。

从HTTP到MIME协议遵循的代理和网关要确保消息在那个协议安全传输上是用正确的格式和正确的编码,“安全传输”是通过使用的协议的限制而被定义的。这样一个代理或网关应该用合适的Content-Transfer-Encoding头域来标记数据如果这样做将提高安全传输的可能性。
19.4.6 Transfer-Encoding头域的介绍

HTTP/1.1介绍了Transfer-Encoding头域(14.41节)。代理/网关在转发经由MIME协议的消息之前必须移除任何传输编码。

一个解码"chunked"传输代码(3.6节)的程序可以用代码表示如下:

length := 0 

read chunk-size, chunk-extension (if any) and CRLF 

while (chunk-size > 0) { 

read chunk-data and CRLF 

append chunk-data to entity-body 

length := length + chunk-size 

read chunk-size and CRLF 

} 

read entity-header 

while (entity-header not empty) { 

append entity-header to existing header fields 

read entity-header 

} 

Content-Length := length 

Remove "chunked" from Transfer-Encoding 
19.4.7 MHTML和行长度限制

和MHTML实现共享代码的HTTP实现需要了解MIME行长度限制。因为HTTP没有这个限制,HTTP并不折叠长行。用HTTP传输的MHTML消息遵守所有MHTML的规定,包括行长度的限制和折叠,规范化等,因为HTTP传输所有消息主体(见3.7.2)并且不解析消息的内容和消息中包含任何MIME头域。
19.5 其它特征

RFC 1945和RFC 2068里一些协议元素被一些已经存在的HTTP实现使用,但是这些协议元素对于大多数HTTP/1.1应用程序既不兼容也不正确。实现者被建议去了解这些特征,但是不能依赖于它们的出现或不依赖于与其它HTTP/1.1应用程序的互操作性。这些特征中的一些特征描述了实验性的特征,以及还有一些特征描述了没有在基本HTTP/1.1规范里被描述的实验性部署特征。

一些其它头域,如Content-Dispositon和Title头域,他们来自于SMTP和MIME协议,他们同样经常被实现(见2076[37]).
19.5.1 Content-Disposition

Content-Disposition响应头域被建议作为一个这样的用途,那就是如果用户请求要使内容被保存为一个文件,那么此头域被源服务器使用去建议的一个缺省的文件名。此用途来自于RFC1806[35]关于对Content-Disposition的定义。

content-disposition = "Content-Disposition" ":" 

disposition-type *( ";" disposition-parm )

disposition-type = "attachment" | disp-extension-token 

disposition-parm = filename-parm | disp-extension-parm 

filename-parm = "filename" "=" quoted-string 

disp-extension-token = token 

disp-extension-parm = token "=" ( token | quoted-string )

一个例子是:

Content-Dis; filename="fname.ext" 

接收用户的代理不应该(SHOULD NOT)关注任何在filename-parm参数中出现的文件路径信息,这个参数被认为在这次仅仅是应用于HTTP实现。文件名应该(SHOULD)只被当作一个终端组件。

如果此头域用于一个Content-Type为application/octet-stream响应里,那么含义就是用户代理不应该展现响应,但是它应该直接进入一个‘保存响应为…’对话框。

见15.5节关于Content-Disposition的的安全问题。
19.6 和以前版本的兼容

要求和以前的版本的兼容超出了协议规范的范围。然而HTTP/1.1有意设计成很容易支持以前的版本。必须值得注意的是,在写这份规范的时候,我们希望商业的HTTP/1.1服务器去:

--接受HTTP/0.9,1.0和1.1请求的请求行(Request-Line)格式;

--理解HTTP/0.9,1.0或1.1格式中的任何有效请求;

--恰当地用客户端使用的主要版本来响应。

并且我们希望HTTP/1.1的客户端:

--接受HTTP/1.0和1.1响应的状态行(Status-Line)格式;

--懂得HTTP/0.9,1.0或1.1的格式的任何有效的响应。

对大多数HTTP/1.0的实现,每一个连接要在请求之前被客户端建立,并且在发送响应之后要被服务器关闭。一些实现了在RFC 2068 [33]的19.7.1节描述的持久连接的Keep-Alive版本。 
19.6.1对HTTP/1.0的改变 

这一部分总结HTTP/1.0和HTTP/1.1之间主要的区别。 
19.6.1.1 对多主机web服务器和保留IP地址简化的改变

客户端和服务器都支持Host请求头域,并且如果Host请求头域在HTTP/1.1请求里没有出现必须报告一错误,并且服务器能接受一个绝对URIs(5.1.2节),这些要求是此规范里最重要的改变。

旧的HTTP/1.0客户端会认为IP地址和服务器是一对一关系;没有其它机制去区分IP地址和目标服务器。上面的改变将允许互联网,一旦旧客户端不再普遍使用时,可以去支持一个IP地址对应多个web站点的情况,这大大简化了大型的web运行服务器,在那上面上分配多个IP地址给一个主机(host)会产生严重问题。互联网照样能恢复这样一个IP地址,此IP地址作为特殊目的被分配给被用于根级(root-level)HTTP URLs的域名。给定web的增长速度和服务器的部署数量,那么所有HTTP实现(包括对已存HTTP/1.0应用程序)应该正确地满足下面这些需求:

--客户端和服务器都必须支持Host请求头域。

--发送HTTP/1.1请求的客户端必须发送Host头域。

--如果HTTP/1.1请求不包括Host请求头域,服务器必须报告错误400(Bad Request)。

--服务器必须接受绝对URIs(absolute URIs)。 
19.6.2和HTTP/1.0持久连接的兼容

一些客户端和服务器可能希望和一些以前持久连接实现的HTTP/1.0客户端和服务器保持兼容。HTTP/1.0持久连接需要显式地协商,因为持久连接不是HTTP/1.0的缺省行为。关于持久连接的HTTP/1.0实验性实现存在缺陷,并且HTTP/1.1里的新的功能被设计成去矫正这些问题。这个缺陷是:一些已经存在的1.0客户端可能会发送Keep-Alive头域给不理解持久连接的代理,然后代理会把此Keep-Alive转发给下一个内向(inbound)服务器。结果是HTTP/1.0客户端必须禁止利用Keep-Alive,当和代理会话的时候。

然而,和代理进行会话最重要是利用持久连接,所以那个禁止很显然不能被接受。因此,我们需要一些其它的机制去指明需要一个持久连接,并且它必须能安全地被使用甚至是当和忽略持久连接的旧代理会话。持久连接缺省是为HTTP/1.1消息的;为了声明非持久连接(见14.10节),我们介绍一个新的关键字(Connection:close)。

持久连接的源HTTP/1.0的形式(Connection: Keep-Alive 和 Keep-Alive 头域)在RFC2068里说明
19.6.3对RFC 2068的改变

这篇规范已经被仔细的审查来纠正关键字的用法和消除它们的歧义;RFC 2068在遵守RFC 2119 [34] 制定的协定方面有很多问题。

澄清哪个错误代码将会使入流服务器失灵(例如DNS失灵)。(10.5.5节)

CREATE有一个特点当一个资源第一次被创建的时候必须需要一个Etag。(10.2.2节)

Content-Base头域从此规范里删除了:它无法广泛的实现,并且在没有健壮的扩展机制的情况下,没有简单的,安全的方式去介绍它。并且,它以一种相似的而不是相同的方式在MHTML[45]里被使用。 

略…..
20 索引 (Index) 
21 全部版权声明

略…..

xenserver中手工给vm添加硬盘及修改cpu、内存

xenserver中的GUI操作功能不全,但命令行下的操作功能齐全而且强大,简单介绍两个
一、给vm添加硬盘
1.获得sr的uuid,新建一个vdi
xe vdi-create sr-uuid=181b140b-2ce7-2a47-eb06-69f10ea696cc name-label=be11 type=user virtual-size=100GiB(单位为MiB,KiB,GiB)
返回vdi uuid:
fb6cb3a9-98dd-4ff7-b49e-08ff34c80671
2.新建一个vbd
xe vbd-create vdi-uuid=fb6cb3a9-98dd-4ff7-b49e-08ff34c80671 vm-uuid=9a1772d5-8eb0-9e48-460b-e7159c33e0ae(需要添加硬盘的vm uuid) device=1(设备号为vm里硬盘数目的顺延,从0开始,比如原来有2个硬盘,则device=2,原来有一个,则device=1) type=Disk(如果是添加光驱,则为CD) mode=RW
返回vbd uuid
31640a57-33e1-699f-22e1-7162770184b8
3.attach新建的vbd
xe vbd-plug uuid=31640a57-33e1-699f-22e1-7162770184b8
ok,在vm中可以使用新硬盘了

二、修改vm的cpu数量
1、确认目前cpu数量
   xe vm-param-list uuid=546f896a-ebe6-8071-2c31-b9214dc1d1b5 |grep VCPUs-
返回
                     VCPUs-params (MRW):
                     VCPUs-max ( RW): 2
              VCPUs-at-startup ( RW): 1
                  VCPUs-number ( RO): 2
             VCPUs-utilisation (MRO): 0: 0.000; 1: 0.000
可以修改的是VCPUs-max(系统最多使用的cpu)、VCPUs-at-startup ( 系统启动时使用的cpu,可以用来热添加cpu测试)
2、修改cpu数量
  xe vm-param-set VCPUs-max=1 uuid=546f896a-ebe6-8071-2c31-b9214dc1d1b5

三、修改vm的memory数量
1、确认目前memory
xe vm-param-list uuid=546f896a-ebe6-8071-2c31-b9214dc1d1b5 |grep -i memory|more
返回
                 memory-actual ( RO): 0
                 memory-target ( RO): 1073741824
             memory-static-max ( RW): 2147483648
            memory-dynamic-max ( RW): 2147483648
            memory-dynamic-min ( RW): 2147483648
             memory-static-min ( RW): 16777216
需要修改的是memory-static-max ( RW): 2147483648
            memory-dynamic-max ( RW): 2147483648
            memory-dynamic-min ( RW): 2147483648
目前为2g
2、修改memory
xe vm-param-set memory-dynamic-max=1073741824  memory-dynamic-min=1073741824  memory-static-max=1073741824
将内存改为1g