• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 内容协商

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

    作为更复杂的请求的示例,此浏览器已配置为接受法语和英语,但更喜欢法语,并接受各种媒体类型,比纯文本或其他文本类型更喜欢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服务器提供对名称空间内资源表示的访问,每种表示形式都是具有定义的媒体类型,字符集,编码等的字节序列形式。每个资源都可以关联在任何给定时间具有零个,一个或多个表示。如果有多种表示形式,则该资源称为可转让资源,并且每种表示形式都称为“变体”。其中用于流通资源的变异而变化的方式被称为谈判。

    在httpd中进行协商

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

    • 使用类型映射(,一个*.var文件),其中包含姓名的明确变种文件,或
    • 使用“ MultiViews”搜索,服务器进行隐式文件名模式匹配,然后从结果中进行选择。

    使用类型图文件

    类型映射是与名为的处理程序相关联的文档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,以模拟所需的行为。它还会将格式为“ type /*”的通配符的q值设置为0.02(因此,与通配符“*/*”相比,它们的优先级更高。如果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.en.html
    • foo.html.en
    • foo.en.html.gz

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

    FilenameValid hyperlinkInvalid hyperlink
    foo.html.enfoo
    foo.html
    -
    foo.en.htmlfoofoo.html
    foo.html.en.gzfoo
    foo.html
    foo.gz
    foo.html.gz
    foo.en.html.gzfoofoo.html
    foo.html.gz
    foo.gz
    foo.gz.html.enfoo
    foo.gz
    foo.gz.html
    foo.html
    foo.html.gz.enfoo
    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环境变量。