We can't find the internet
Attempting to reconnect
## 内容协商与转码
一个 URL 常常需要代表若干不同的资源。例如那种需要以多种语言提供其内容的网站站点
。
HTTP 提 供了内容协商方法,允许客户端和服务器作这样的决定。通过这些方法,单一的
URL 就可以代表不同的资源(比如,同一个网站页面的法语版和英语版)。这些不同的版本称
为变体。
### 内容协商技术
共有 3 种不同的方法可以决定服务器上哪个页面最适合客户端:
- 让客户端来选择
- 服务器自动判定
- 让中间代理来选
这 3 种技术分别称为
- 客户端驱动的协商
- 服务器驱动的协商
- 透明协商
| 技术 | 工作原理 | 优点 | 缺点 |
| ---------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| 客户端驱动 | 客户端发起请求,服务器发送可选项的列表,客户端选择 | 在服务器端的实现最容易。客户端可以选择最合适的内容 | 增加了时延:为了获得正确的内容,至少要发送两次请求 |
| 服务器驱动 | 服务器检查客户端的请求首部集并决定提供哪个版本的页面 | 比客户端驱动的协商方式要快。 HTTP 提供了 q 值机制,允许服务器近似匹配,还提供了 Vary 首部供服务器告知下游的设备如何对请求估值 | 如果结论不是很明确(比如首部集不匹配),服务器要做猜测 |
| 透明 | 某个中间设备(通常是缓存代理)代表客户端进行请求协商 | 免除了 Web 服务器的协商开销。比客户端驱动的协商要快 | 关于如何进行透明协商,还没有正式的规范 |
### 客户端驱动的协商
从实现原理上来说,服务器实际上有两种方法为客户端提供选项:
- 一是发送回一个 HTML 文档,里面有到该页面的各种版本的链接和每个版本的描述信息;
- 另一种方法是发送回 HTTP/1.1 响应时,使用 300 Multiple Choices 响应代码。客户端
浏览器 收到这种响应时,在前一种情况下,会显示一个带有链接的页面; 在后一种情况
下,可能会弹出对话窗口,让用户做选择。不管怎么样,决定是由客户端的浏览器用户
作出的。
### 服务器驱动的协商
有以下两种机制可供 HTTP 服务器评估发送什么响应给客户端比较合适。
- 检查内容协商首部集。服务器察看客户端发送的 Accept 首部集,设法用相应的 响应首
部与之匹配。
- 根据其他(非内容协商)首部进行变通。例如,服务器可以根据客户端发送的 User-Agent
首部来发送响应。
#### 内容协商首部集
| 首部 | 描述 |
| --------------- | -------------------------- |
| Accept | 告知服务器发送何种媒体类型 |
| Accept-Language | 告知服务器发送何种语言 |
| Accept-Charset | 告知服务器发送何种字符集 |
| Accept-Encoding | 告知服务器采用何种编码 |
注意,由于 HTTP 是无状态的协议(表示服务器不会在不同的请求之间追踪客户端 的偏好
),所以客户端必须在每个请求中都发送其偏好信息。
#### 内容协商首部中的质量值
客户端可以发送下列形式的 Accept-Language 首部:
```http
Accept-Language: en;q=0.5, fr;q=0.0, nl;q=1.0, tr;q=0.0
```
其中 q 值的范围从 0.0 ~ 1.0(0.0 是优先级最低的,而 1.0 是优先级最高的)。上面 列
出的那个首部,说明该客户端最愿意接收荷兰语(缩写为 nl)文档,但英语(缩 写为 en)文
档也行;无论如何,这个客户端都不愿意收到法语(缩写为 fr)或土耳 其语(缩写为 tr)的版
本。
#### 随其他首部集而变化
服务器也可以根据其他客户端请求首部集来匹配响应,比如 User-Agent 首部。
在这种情况下,没有 q 值机制可供查找“最近似”的匹配。服务器或者去找完全匹配,或者
简单地有什么就给什么,这取决于服务器的实现。
由于缓存需要尽力提供所缓存文档中正确的“最佳”版本,HTTP 协议定义了服务器在响应中
发送的 Vary 首部。这个首部告知缓存(还有客户端和所有下游的代理)服务器根据哪些首部
来决定发送响应的最佳版本。
#### Apache 中的内容协商
1. 使用 type-map 文件
可以在服务器的配置文件中设 置 handler 来说明 type-map 文件的后缀名。
```apache
AddHandler type-map .var
```
这里给出一个 type-map 文件示例:
```apache
URI: joes-hardware.html
URI: joes-hardware.en.html
Content-type: text/html
Content-language: en
URI: joes-hardware.fr.de.html
Content-type: text/html;charset=iso-8859-2
Content-language: fr, de
```
根据这个 type-map 文件, Apache 服务器就知道要发送 joes-hardware.en.html 给请求
英语版的客户端,发送 joes-hardware.fr.de.html 给请求法语版的客户端。 Apache 服务
器也支持质量值,具体信息请参阅它的文档。
2. 使用 MultiView
为了使用 MultiView,必须在网站目录下的 `access.conf` 文件中的适当小节
(<Directory>、 <Location>,或 <Files>)使用 OPTION 指令来启用它。
如果启用了 MultiView,而浏览器又请求了名为 joes-hardware 的资源,服务器就会查找
所有名字中含有 joes-hardware 的文件,并为它们创建 type-map 文件。服务器会 根据名
字猜测其对应的内容协商首部集。例如,法语版的 joes-hardware 应当含有 .fr。
#### 服务器端扩展
另一种在服务器端实现内容协商的方法是使用服务器端扩展
### 透明协商
透明协商机制试图从服务器上去除服务器驱动协商所需的负载,并用中间代理来代表客户端
以使与客户端的报文交换最小化。假定代理了解客户端的预期,这样就可以代表客户端与服
务器协商(在客户端请求内容的时候,代理已经收到了客户端的预期)。为了支持透明内容协
商,服务器必须有能力告知代理,服务器需要检查哪些请求首部,以便对客户端的请求进行
最佳匹配。 HTTP/1.1 规范中没有定义任何透明协商机制,但定义了 Vary 首部。服务器在
响应中发送了 Vary 首部,以告知中间节点需要使用哪些请求首部进行内容协商。
代理缓存可以为通过单个 URL 访问的文档保存不同的副本。如果服务器把它们的决 策过程
传给缓存,这些代理就能代表服务器与客户端进行协商。缓存同时也是进行 内容转码的好
地方,因为部署在缓存里的通用转码器能对任意服务器,而不仅仅是 一台服务器传来的内
容进行转码。
#### 进行缓存与备用候选
对内容进行缓存的时候是假设内容以后还可以重用。然而,为了确保对客户端请求 回送的
是正确的已缓存响应,缓存必须应用服务器在回送响应时所用到的大部分决 策逻辑。
#### Vary 首部
HTTP 的 Vary 响应首部中列出了所有客户端请求首部,服务器可用这些首部来选择文档或
产生定制的内容(在常规的内容协商首部集之外的内容)。
例如,若所提供的 文档取决于 User-Agent 首部,Vary 首部就必须包含 User-Agent。
当新的请求到达时,缓存会根据内容协商首部集来寻找最佳匹配。但在把文档提供 给客户
端之前,它必须检查服务器有没有在已缓存响应中发送 Vary 首部。如果有 Vary 首部,那
么新请求中那些首部的值必须与旧的已缓存请求里相应的首部相同。因为服务器可能会根据
客户端请求的首部来改变响应,为了实现透明协商,缓存必须为每个已缓存变体保存客户端
请求首部和相应的服务器响应首部。
### 转码
如果服务器没有能满足客户端需求的文档会怎么样呢?服务器可以给出一个错误响应。但理
论上,服务器可以把现存的文档转换成某种客户端可用的文档。这种选项称为转码。
#### 格式转换
格式转换是指将数据从一种格式转换成另一种格式,使之可以被客户端查看。
- 通过 HTML 到 WML 的转换,无线设备就可以访问通常供桌面客户端查看的文档了。
- 通过慢速连接访问 Web 页面的客户端并不需要接收高分辨率图像,如果通过格式转换降
低图像分辨率和颜色来减小图像文件大小的话,这类客户端就能更容易地查看图像比较丰
富的页面了。
格式转换可以由内容协商首部集来驱动,但也能由 User-Agent 首部来驱动。
#### 信息综合
从文档中提取关键的信息片段称为信息综合(information synthesis),这是一种有用的转
码操作。这种操作的例子包括根据小节标题生成文档的大纲,或者从页面中删除广告和商标
。
根据内容中的关键字对页面分类是更精细的技术,有助于总结文档的精髓。这种技术常用于
Web 页面分类系统中,比如门户网站的 Web 页面目录。
#### 内容注入
前面描述的两类转码通常会减少 Web 文档的内容,但还有另一类转换会增加文档的内容,
即内容注入转码。
内容注入转码的例子有自动广告生成器和用户追踪系统。
#### 转码与静态预生成的对比
转码的替代做法是在 Web 服务器上建立 Web 页面的不同副本,例如一个是 HTML,一个是
WML; 一个图像分辨率高,一个图像分辨率低; 一个有多媒体内容,一个没有。
对单一的根页面进行即时转换,是比静态的预生成更容易的解决方案。不过有时候其中一些
计算可以由第三方进行,这样就减少了 Web 服务器上的计算负荷——比如可以由代理或缓存
中的外部 Agent 完成转换。
### 下一步计划
- HTTP 中的内容协商受到一些性能方面的限制。在各种变体中搜索合适的内容,或尽力“猜
测”最佳匹配,都会有很大开销。有没有什么办法能专注内容协商协议以使这个过程更高
效? RFC 2295 和 RFC2296 尝试着对这个问题进行了研究,以提供透明的 HTTP 内容协商
。
- HTTP 不是唯一需要进行内容协商的协议。在其他一些情况下,客户端也需要和服务器交
互以便获得对客户端请求来说最好的答案,流媒体和传真就是另外两个 例子。能否在
TCP/IP 应用层协议之上开发出通用的内容协商协议呢?内容协商工作组(Content
Negotiation Working Group)就是专门为这个问题而成立的。这个工作组目前已经停止工
作了,不过它提出了若干个 RFC。
### 更多信息
- http://www.ietf.org/rfc/rfc2616.txt
RFC 2616,“Hypertext Transfer Protocol-HTTP/1.1”(“超文本传输协议 HTTP/1.1”),这
是 HTTP 协议的当前版本,也是 HTTP/1.1 的官方规范。这份规范行文流畅、 组织良好,
是份详实的 HTTP 参考文献。不过对那些希望学习 HTTP 背后的各种 概念和决策动机、弄
清理论与实践不同之处的读者来说,它就不是很理想了。我们希望本书能补足背后的这些概
念,使读者能更好地利用这份规范。
- http://www.ietf.org/rfc/rfc2295.txt
RFC 2295,“Transparent Content Negotiation in HTTP”(“HTTP 中的透明内容协 商”),
这是一份备忘录,描述了建立在 HTTP 之上的透明内容协商协议。这份备忘录目前还是实验
性的。
- http://www.ietf.org/rfc/rfc2296.txt
RFC 2296,“HTTP Remote Variant Selection Algorithm RVSA 1.0”(“HTTP 远程变体选择算
法 RVSA1.0”),这份备忘录描述了为特定的 HTTP 请求透明地选择“最佳”内容的算法。这份
备忘录目前还是实验性的。
- http://www.ietf.org/rfc/rfc2936.txt
RFC 2936,“HTTP MIME Type Handler Detection”(“HTTP MIME 类型处理器检 测”),这份备
忘录描述了一种用来判定浏览器支持的 MIME 类型处理器的方法。如果 Accept 首部不够明
确的话,这种方法就能派上用场。
- http://www.imc.org/ietf-medfree/index.htm
这个链接指向内容协商(简称 CONNEG)工作组网站。该工作组专注于 HTTP、 传真和打印方
面的透明内容协商。这个工作组目前已停止工作。