<-
Apache HTTP 服务器 2.4 > 内容协商

内容协商

Apache HTTPD支持HTTP / 1.1规范中所述的内容协商。它可以根据浏览器提供的媒体类型,语言,字符集和编码的首选项来选择资源的最佳表示形式。它还实现了一些功能,可以更智能地处理来自发送不完整协商信息的浏览器的请求。

内容协商由mod_negotiation模块提供 ,默认情况下已编译。

支持Apache!

也可以看看

最佳

关于内容协商

资源可能有几种不同的表示形式。例如,它可能以不同的语言或不同的媒体类型或它们的组合提供。选择最合适的选择的一种方法是为用户提供索引页,然后让他们选择。但是,服务器通常可以自动选择。之所以可行,是因为浏览器可以在每个请求中发送有关他们喜欢哪种表示形式的信息。例如,浏览器可能指示希望以法语查看信息,如果可能,则以英语显示。浏览器通过请求中的标头指示其首选项。要仅请求法语表示,浏览器将发送

Accept-Language: fr

请注意,只有在可以选择表示形式并且它们随语言而变化时,才会应用此首选项。

作为更复杂的请求的示例,此浏览器已配置为接受法语和英语,但更喜欢法语,并接受各种媒体类型,比纯文本或其他文本类型更喜欢HTML,比其他媒体类型更喜欢GIF或JPEG ,但也允许任何其他媒体类型作为最后手段:

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

httpd支持HTTP / 1.1规范中定义的“服务器驱动”内容协商。它完全支持 AcceptAccept-LanguageAccept-CharsetAccept-Encoding 请求头。httpd还支持“透明”内容协商,这是RFC 2295和RFC 2296中定义的实验性协商协议。它不提供对这些RFC中定义的“功能协商”的支持。

资源是由URI(RFC 2396)识别的概念实体。像Apache HTTP Server这样的HTTP服务器提供对名称空间内资源表示的访问,每种表示形式都是具有定义的媒体类型,字符集,编码等的字节序列形式。每个资源都可以关联在任何给定时间具有零个,一个或多个表示。如果有多个表示形式,则该资源被称为可协商资源,并且其每个表示形式都称为Variant。其中用于流通资源的变异而变化的方式被称为谈判。

最佳

在httpd中进行协商

为了协商资源,需要为服务器提供有关每个变体的信息。这可以通过以下两种方式之一来完成:

使用类型图文件

类型映射是一个文档,该文档与名为的处理程序相关联type-map(或者,对于与旧版httpd配置具有向后兼容性,则为MIME-type application/x-type-map)。请注意,要使用此功能,必须在配置中设置一个处理程序,该处理程序将文件后缀定义为type-map;最好用

AddHandler type-map .var

在服务器配置文件中。

类型映射文件应与它们描述的资源具有相同的名称,后跟扩展名 .var。在下面显示的示例中,资源被命名为foo,因此类型映射文件被命名为 foo.var

该文件应为每个可用变体提供一个条目。这些条目由连续的HTTP格式的标题行组成。不同变体的条目由空白行分隔。空行在条目中是非法的。通常,以一个用于整个合并实体的条目开始一个映射文件(尽管这不是必需的,并且如果存在则将被忽略)。下面显示了一个示例地图文件。

该文件中的URI相对于类型映射文件的位置。通常,这些文件与类型映射文件位于同一目录中,但这不是必需的。您可以为与映射文件位于同一服务器上的任何文件提供绝对或相对URI。

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

还要注意,即使打开“多视图”,类型映射文件也将优先于文件名的扩展名。如果变体具有不同的源质量,则可以通过媒体类型的“ qs”参数来表示,如下图所示(以JPEG,GIF或ASCII艺术形式提供):

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.000的任何变体。没有“ qs”参数值的变体的qs系数为1.0。qs参数指示此变量与其他可用变量相比的相对“质量”,而与客户端的功能无关。例如,如果JPEG文件试图表示照片,则其源质量通常比ASCII文件高。但是,如果要表示的资源是原始ASCII艺术,则ASCII表示的源质量将比JPEG表示的源质量高。因此,qs值特定于给定的变量,具体取决于它代表的资源的性质。

可以在mod_negotiation typemap文档中找到已识别的标头的完整列表。

多视图

MultiViews是每个目录的选项,这意味着可以使用,或部分 (如果正确设置)中的Options 指令在文件中进行设置 。注意 没有设置;您必须按名称要求。<Directory><Location><Files>httpd.confAllowOverride.htaccessOptions AllMultiViews

效果MultiViews如下:如果服务器收到一个请求/some/dir/foo,如果 /some/dir已经MultiViews启用,并 /some/dir/foo不会存在,则服务器会寻找一个名为foo的文件的目录*,并有效假货一个类型的地图,名称所有这些文件。 ,为它们分配相同的媒体类型和内容编码(如果客户端按名称要求提供其中一种)。然后,它选择最符合客户要求的匹配项。

MultiViewsDirectoryIndex如果服务器尝试索引目录,则也可能适用于搜索以伪指令命名的文件。如果配置文件指定

DirectoryIndex index

那么服务器将在index.html 和之间进行仲裁(index.html3如果两者均存在)。如果两者都不index.cgi存在,则服务器将运行它。

如果在读取目录时找到的文件之一没有可识别mod_mime其文件集,内容类型,语言或编码的扩展名,则结果取决于MultiViewsMatch指令的设置。该指令确定处理程序,过滤器和其他扩展类型是否可以参与MultiViews协商。

最佳

谈判方式

在httpd从类型映射文件或目录中的文件名获取给定资源的变体列表之后,它会调用两种方法之一来确定要返回的“最佳”变体(如果有)。为了使用httpd的内容协商功能,不必知道实际上如何进行协商的任何细节。但是,本文的其余部分将为感兴趣的人介绍所使用的方法。

有两种协商方法:

  1. 在正常情况下,使用带有httpd算法的服务器驱动的协商。以下将详细说明httpd算法。使用此算法时,httpd有时可以“弄乱”特定尺寸的质量因数以获得更好的结果。下面将详细介绍httpd修饰质量因子的方式。
  2. 当浏览器通过RFC 2295中定义的机制专门请求透明内容协商时,将使用透明内容协商。此协商方法使浏览器可以完全控制决定“最佳”变体,因此结果取决于浏览器使用的特定算法。作为透明协商过程的一部分,浏览器可以要求httpd运行RFC 2296中定义的“远程变量选择算法”。

谈判范围

尺寸 笔记
媒体类型 浏览器使用Accept 标题字段指示首选项。每个项目都可以具有关联的品质因数。变体描述也可以具有品质因数(“ qs”参数)。
语言 浏览器使用Accept-Language标题字段指示首选项 。每个项目都可以有一个品质因数。变体可以与一种,一种或多种语言关联。
编码方式 浏览器用Accept-Encoding标题字段指示首选项 。每个项目都可以有一个品质因数。
字符集 浏览器用Accept-Charset标题字段指示首选项 。每个项目都可以有一个品质因数。变体可以将字符集指示为媒体类型的参数。

httpd协商算法

httpd可以使用以下算法来选择“最佳”变体(如果有)以返回到浏览器。该算法无法进一步配置。其操作如下:

  1. 首先,对于协商的每个维度,请检查相应的Accept *标头字段,并为每个变量指定质量。如果任何尺寸的Accept *标头表示此变体不可接受,请消除它。如果没有其他型号,请转到步骤4。
  2. 通过淘汰过程选择“最佳”变体。依次进行以下每个测试。消除了每次测试未选择的任何变体。每次测试后,如果只剩下一个变体,请选择它作为最佳匹配,然后继续执行步骤3。如果还有一个以上的变体,请继续进行下一个测试。
    1. Accept 标头中的质量因子与该变体媒体类型的源质量因子相乘,然后选择具有最高值的变体。
    2. 选择具有最高语言品质因数的变体。
    3. 使用Accept-Language标题中的语言顺序(如果存在)或LanguagePriority 伪指令中的语言顺序(如果存在),选择具有最佳语言匹配的变体 。
    4. 选择具有最高“级别”媒体参数的变体(用于提供text / html媒体类型的版本)。
    5. Accept-Charset 标题行所示,选择具有最佳字符集媒体参数的变体。除非明确排除,否则Charset ISO-8859-1是可以接受的。具有text/* 媒体类型但未明确与特定字符集关联的变体假定为在ISO-8859-1中。
    6. 选择那些关联的字符集媒体参数不是 ISO-8859-1的变量。如果没有此类变量,请选择所有变量。
    7. 选择具有最佳编码的变体。如果存在带有用户代理可接受的编码的变体,请仅选择这些变体。否则,如果混合使用编码变体和非编码变体,则仅选择未编码变体。如果所有变体均已编码或所有变体均未编码,请选择所有变体。
    8. 选择内容长度最小的变体。
    9. 选择其余的第一个变体。这将是类型映射文件中第一个列出的文件,或者是从目录中读取变体的文件,当使用ASCII代码顺序进行排序时,其文件名将排在第一位。
  3. 该算法现在选择了一个“最佳”变体,因此将其作为响应返回。HTTP响应标头 Vary设置为指示协商的范围(浏览器和缓存可在缓存资源时使用此信息)。结束。
  4. 到达此处表示未选择任何变体(因为浏览器不接受任何变体)。返回406状态(表示“没有可接受的表示形式”),其响应正文由列出可用变体的HTML文档组成。还要设置HTTP Vary标头以指示差异的大小。
最佳

摆弄质量价值观

httpd有时会通过严格解释上面的httpd协商算法来改变质量值。对于没有发送完整或准确信息的浏览器,这是从算法中获得更好的结果。一些最受欢迎的浏览器会发送 Accept标头信息,否则,在许多情况下,标头信息会导致选择错误的变体。如果浏览器发送了完整且正确的信息,这些提琴将不会被应用。

媒体类型和通配符

Accept:请求报头指示介质类型的偏好。它还可以包括“通配符”媒体类型,例如“ * / *”匹配任何字符串的“ image / *”或“ * / *”。因此,请求包括:

Accept: image/*, */*

表示以“ image /”开头的任何类型都可以接受,其他任何类型也可以。一些浏览器除了可以处理的显式类型外,还会例行发送通配符。例如:

Accept: text/html, text/plain, image/gif, image/jpeg, */*

这样做的目的是表明首选显式列出的类型,但是如果可以使用其他表示形式,也可以。使用显式的质量值,浏览器真正想要的是:

Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01

显式类型没有品质因数,因此它们的默认优先级为1.0(最高)。通配符* / *的优先级较低,为0.01,因此,如果没有任何变量与显式列出的类型匹配,则仅返回其他类型。

如果Accept:标头根本不包含任何 q因子,则httpd将q *的“ * / *”值(如果存在)设置为0.01,以模拟所需的行为。还将“类型/ *”格式的通配符的q值设置为0.02(因此,与“ * / *”匹配时,通配符的q值更可取。如果Accept:标头上的任何媒体类型 包含aq因数,则不会应用这些特殊值,因此,来自浏览器的请求会发送明确的信息以按预期开始工作。

语言协商异常

httpd 2.0中的新增功能,已将一些例外添加到协商算法中,以在语言协商无法找到匹配项时允许正常回退。

当客户端请求服务器上的页面,但服务器找不到与Accept-language浏览器发送的页面匹配的页面时, 服务器将向客户端返回“ No Acceptable Variant”或“ Multiple Choices”响应。为了避免这些错误消息,可以将httpd配置为Accept-language在这种情况下忽略,并提供与客户端的请求不明确匹配的文档。该 ForceLanguagePriority 指令可用于覆盖这些错误消息之一或全部,并以LanguagePriority 指令的形式替代服务器的判断 。

当找不到其他匹配项时,服务器还将尝试匹配语言子集。例如,如果客户端请求使用en-GB英式英语语言的文档,则HTTP / 1.1标准通常不允许服务器将其与标记为simple的文档进行匹配 en。(请注意,几乎肯定会包含配置错误,en-GB而不是包含enAccept-Language标头中,因为读者不太可能会理解英式英语,但通常不会理解英语。不幸的是,许多当前的客户端具有类似于此的默认配置。)但是,如果没有其他语言匹配是可能的,并且服务器将返回“ No Acceptable Variants”错误或回退到LanguagePriority,服务器将忽略该子集规范和匹配en-GB 反对en文件。隐式地,httpd会将父语言以非常低的质量值添加到客户的可接受语言列表中。但是请注意,如果客户端请求“ en-GB; q = 0.9,fr; q = 0.8”,并且服务器具有指定为“ en”和“ fr”的文档,则将返回“ fr”文档。这对于保持符合HTTP / 1.1规范并与正确配置的客户端有效地工作是必需的。

为了支持高级技术(例如cookie或特殊的URL路径)来确定用户的首选语言,因为httpd 2.0.47可以mod_negotiation识别环境变量 prefer-language。如果存在并且包含适当的语言标签,mod_negotiation将尝试选择匹配的变体。如果没有此类变体,则适用正常的协商过程。

SetEnvIf Cookie "language=(.+)" prefer-language=$1
Header append Vary cookie
最佳

透明内容协商的扩展

httpd扩展了透明内容协商协议(RFC 2295),如下所示。{encoding ..}变体列表中使用一个新元素来标记变体,这些变体仅可用于特定的内容编码。扩展了RVSA / 1.0算法(RFC 2296)的实现,以识别列表中的编码变体,并在根据Accept-Encoding请求标头接受编码时,将其用作候选变体。在选择最佳变体之前,RVSA / 1.0实现不会将计算出的质量因数四舍五入到小数点后五位。

最佳

关于超链接和命名约定的注意事项

如果使用语言协商,则可以在不同的命名约定之间进行选择,因为文件可以具有多个扩展名,并且扩展名的顺序通常是不相关的(有关详细信息,请参见mod_mime文档)。

一个典型的文件有一个MIME类型的扩展名(例如html),也许编码扩展(例如gz),当然还有语言扩展(例如en)当我们有这个文件的不同语言版本。

例子:

以下是一些文件名示例以及有效和无效的超链接:

文件名 有效的超链接 无效的超链接
foo.html.en foo
foo.html
--
foo.en.html foo.html
foo.html.en.gz foo
foo.html
foo.gz
foo.html.gz
foo.en.html.gz foo.html
foo.html.gz
foo.gz
foo.gz.html.en foo
foo.gz
foo.gz.html
foo.html
foo.html.gz.en foo
foo.html
foo.html.gz
foo.gz

查看上表,您会发现始终可以使用名称,而无需在超链接中添加任何扩展名(例如foo)。好处是您可以隐藏文档rsp的实际类型。文件,以后可以更改它,例如,从更改htmlshtmlcgi不更改任何超链接引用。

如果你想继续在超链接(使用MIME类型 foo.html)的语言扩展(包括如果有一个编码扩展)必须在MIME类型的扩展名(右侧例如foo.html.en)。

最佳

关于缓存的注意事项

缓存存储表示形式时,会将其与请求URL关联。下次请求URL时,缓存可以使用存储的表示形式。但是,如果资源在服务器上可协商,则可能导致仅第一个请求的变体被缓存,并且随后的缓存命中可能返回错误的响应。为避免这种情况,httpd通常会将内容协商后返回的所有响应标记为HTTP / 1.0客户端不可缓存。httpd还支持HTTP / 1.1协议功能,以允许缓存已协商的响应。

对于来自HTTP / 1.0兼容客户端(浏览器或缓存)的请求,该指令CacheNegotiatedDocs可用于允许缓存需要协商的响应。该指令可以在服务器配置或虚拟主机中给出,并且不带参数。它对来自HTTP / 1.1客户端的请求没有影响。

对于HTTP / 1.1客户端,httpd发送VaryHTTP响应标头以指示响应的协商维度。缓存可以使用此信息来确定是否可以从本地副本满足后续请求。为了鼓励缓存使用本地副本而不管协商维度如何,请设置force-no-vary 环境变量

可用语言: zh  |  fr  |  ja  |  ko  |  TR 

最佳

注释

注意:
这不是“问答”部分。此处放置的评论应指向有关改进文档或服务器的建议,如果实施或被认为无效/偏离主题,我们的主持人可以将其删除。有关如何管理Apache HTTP Server的问题,应直接指向我们的IRC频道#httpd(位于Freenode上),或发送至我们的邮件列表
目前,此页面已禁用评论。