分类: 系统运维
2012-06-04 15:06:54
协商(Negotiation)
一个资源可能有多种表现方式。比如不同的语言或不同的媒体类型。选择最恰当的形式的一种方式是给用户一个索引页,让他自己选择。但一般服务器可以自动地选择,因为浏览器会在请求里添加它想要的表现形式,比如在头部加入语言信息:
Accept-Language: fr
用户也可以指定多种选择,按优先级排列:
Accept-Language: fr; q=1.0, en; q=0.5
Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
表示法语优先,英语其次。html最优,图片其次,其它类型也都接受。
httpd 根据HTTP/1.1规范,完全支持“服务器驱动”内容协商。它完全支持Accept、Accept-Language、Accept-Charset和 Accept-Encoding请求头部。httpd也支持RFC2295和RFC2296定义的实验性协商协议:“透明”内容协商。但它没有支持这些 RFC定义的“特性协商”。
一个“资源”是由URI(RFC 2396)标识的概念实体。像Apache这样的HTTP服务器提供了对资源“表示”的访问。每个资源在任何时刻可能关联0个、1个或多个表示。如果有多 个表示,资源被称为“可协商的”(negotiable),每个表示被称为一个变体。资源可以表示的方式数量被称为协商的“维度”。
httpd的协商
为了协商一个资源,服务器需要知道它的每一个变体的信息。有两种方式:
使用type map,它显式地给出了包含变体的文件;
使用MultiViews搜索,服务器执行隐式的文件名样式匹配,从结果中选择。
type map是一个与名为type-map的handler关联的一个文档。(为了和更早的httpd配置兼容,它也可以是application/x-type-map的MIME类型。)要使用这个特性,我们必须在配置文件里定义一个handler集来定义一个文件后缀作为type-map。最好的方式为:
AddHandler type-map .var
type map文件名为要描述的资源名加上.var后缀。这个文件应该为每个可用的变体提供一个项,这些项由HTTP格式的头部行组成。变体项之间由空行分隔。例如(foo.var):
URI: foo
URI: foo.en.html
Content-type: text/html
Content-language: en
URI: foo.fr.de.html
Content-type: text/html;charset=iso-8859-2
Content-language: fr, de
文件里的URI是与tpye map文件的相对路径,也可以是绝对路径。通常这些文件和type map文件放在相同目录下,但这不是必需的。
typemap文件的优先比文件名的扩展名高,即使MultiViews被打开。如果变体有不同的源品质,则可以用媒体类型的qs参数来指定:
URI: foo
URI: foo.jpeg
Content-type: image/jpeg; qs=0.8
URI: foo.gif
Content-type: image/gif; qs=0.5
URI: foo.txt
Content-type: text/plain; qs=0.01
qs值的取值范围为0.000到1.000。任何qs值为0的变体不会被选择。没有qs参数的变体默认qs值为1。qs参数指定了与其它变体的相对的“品质”。
MultiViews
是一个基于目录的选项,意味着它可以在
如果/some/dir启用了MultiViews,在收到/some/dir/foo的请求而该目录不存在时,那么目录会查找名为foo.*的文件,并高效地模拟一个type map来命名这些文件,并赋给它们相同的媒体类型和内容编码。之后它根据客户的请求来选择最好的匹配。
如果服务器尝试索引一个目录,那么MultiViews也可以应用于搜索DirectoryIndex指令命名的文件。如果配置文件指定为:
DirectoryIndex index
那么如果index.html和index.html3同时存在时服务器会从它们之间进行选择,如果它们都不存在而有index.cgi,那么服务器就会运行它。
如果在读取一个目录时有文件的扩展名无法被mod_mime识别从而指定它的Charset, Content-Type, Language, or Encoding,那么结果取决于MultiViewsMatch指令的设置。这个指令决定了handler、filter、和其它扩展类型是否可以参与到MultiViews协商中。
协商方法
有两种协商方法:
使用httpd算法的服务器驱动的协商,用于普通情况;
透明内容协商,浏览器使用RFC2295定义的机制发出请求,从而完全控制最好的变体。