在IIS7/8/8.5中指定多种(gzip + brotli)http压缩方案并优先使用brotli。

11
我正在尝试使用“Microsoft IIS的Brotli压缩模块”通过iisspeed.com来启用新的Brotli压缩方案。
如果我在applicationHost.config中更改<httpCompression>配置部分,仅使用Brotli模块,则Brotli压缩模块本身可以正常工作。
问题在于我希望同时拥有gzip和Brotli,而且更喜欢Brotli。
iisspeed.com上的文档建议这样做:
<httpCompression directory="path\to\temp\folder" minFileSizeForComp="50">
        <scheme name="br" dll="path\to\iisbrotli.dll" />
        <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
        ...
</httpCompression>

然而,我发现这并不起作用。
浏览器(此例中为Chrome)发送以下“accept-encoding”头:
accept-encoding: gzip,deflate,sdch,br 这意味着浏览器可以接受Brotli编码br以及gzip。我希望IIS优先使用br而不是gzip,但似乎没有办法在配置中优先考虑每个方案元素。我尝试更改.config文件中的顺序,但没有效果。
即使支持br并且因为它是较小的文件大小而更受欢迎,IIS仍然始终使用gzip。
我已经搜遍了谷歌,发现在IIS 6中有一个针对每个压缩方案的优先级设置,但似乎已在IIS7+中被删除。
它被称为HcPriority并进入了IIS6元数据XML文件。
请参见以下链接:

https://msdn.microsoft.com/en-us/library/ms525366(v=vs.90).aspx

https://blogs.iis.net/ksingla/changes-to-compression-in-iis7

https://forums.iis.net/t/1150520.aspx

有没有办法让IIS7+在客户端支持时优先使用br而不是gzip

2个回答

11

看起来你引用的Brotli模块需要付费许可证,所以我没有尝试过它,但是我在我自己的开源Brotli插件 BrotliIIS 上遇到了类似的问题。

正如你指出的那样,当前浏览器在 Accept-Encoding 头中将Brotli支持显示在 gzipdeflate 之后。

HTTP RFC 没有关于如何从具有相同优先级的多个 Accept-Encoding 值中进行选择的具体指导,因此将 br 内容返回给这些客户端是可以接受的。但是,看起来IIS总是选择与其配置的压缩方案匹配的第一个(从左到右)。

如果您希望同时启用两种方案,您可以在请求进入您的IIS管道时修改 Accept-Encoding 头值。 使用IIS URL Rewrite Module 可以通过简单的规则实现此目的。

Accept-Encoding头由IIS管道中的HTTP_ACCEPT_ENCODING Server Variable表示,并且您可以在它到达压缩模块之前修改它。以下是一个示例配置:

<rewrite>
    <allowedServerVariables>
        <add name="HTTP_ACCEPT_ENCODING" />
    </allowedServerVariables>
    <rules>
        <rule name="Prioritize Brotli">
            <match url=".*" />
            <conditions>
                <add input="{HTTP_ACCEPT_ENCODING}" pattern="\bbr(?!;q=0)\b" />
            </conditions>
            <serverVariables>
                <set name="HTTP_ACCEPT_ENCODING" value="br" />
            </serverVariables>
        </rule>
    </rules>
</rewrite>

上述规则查找Accept-Encoding标头中被单词边界包围的字符串br(且不紧跟着;q=0),并将其重写为简单的br,从而仅给IIS提供一种选择。

请注意,默认的URL重写配置不允许修改HTTP_ACCEPT_ENCODING变量。 allowedServerVariables元素覆盖了该限制,必须在applicationHost.config中进行配置。随后可以在配置层次结构中的任何级别定义重写规则,尽管将其定义为全局可能是最合适的。


我将此标记为答案,因为我认为这是最优雅的解决方案,理论上适用于任何其他类型的插件或模块。这是一种通用解决方案。谢谢。 - theyetiman
我需要将该条目放入applicationHost.config文件中吗? - NGR
这是最简单的解决方案。最少,allowedServerVariables配置必须放在applicationHost.config中。如果需要,可以在web.config中针对站点或文件夹定义rules - saucecontrol

2
从您提供的第二个链接(我强调)中:
如果请求的Accept-Encoding头中出现多个方案,则选择使用的方案取决于首先出现在Accept-Encoding头中的方案(假设没有q因子)。这符合HTTP规范。
此处也有讨论:HTTP: What is the preferred Accept-Encoding for “gzip,deflate”? 如果您使用允许您手动设置请求标头的HTTP客户端(例如PostmanFiddler),或者可以更改请求标头的浏览器扩展程序(例如Chrome的ModHeader),并使用Accept-Encoding:br,gzip,deflate进行相同的请求,您应该看到响应使用Brotli编码,即使gzip和/或deflate也可用。
编辑:我通过将其注册为全局本机模块并在动态和静态压缩模块之前排序,成功地使Brotli模块按预期工作(即在与最优先项并列时始终使用Brotli编码),详见注册全局本机模块

谢谢您的回答,但它并没有真正回答我的问题,即如何让Web服务器决定首选项(而不是手动编写解决方案),而不是浏览器。也许这是不可能的,但我会等待看看是否有人有任何好主意。 - theyetiman
我编辑了我的答案,以反映实现你想要的另一种(并且成功的)方法 - 希望它有所帮助。 - ejohnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接