IIS作为反向代理-从后端服务器对重写的响应进行压缩如何实现?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (214)

我正在实现将请求路由到后端服务器的反向代理。

在功能上,一切工作正常,但我担心来自后端服务器的所有响应都将传输到客户端(Web浏览器)而不进行压缩。

设置如下:

  • 后端服务器在内部域中不可公开访问。托管一个Web应用程序https://internal.app
  • 带有IIS 7.5的前台Web服务器,托管主要公共网站并充当后端服务器的代理。主要网站在https://site.com

我想所有请求路由到https://site.com/app/WHATEVERhttps://internal.app/WHATEVER的方式是透明的客户。

我目前的设置基于URL Rewrite 2.0和应用程序请求路由IIS扩展。一般方法基于以下文章的准则:

有关节web.config的的site.com应用程序:

<system.webServer>
    <rewrite>
        <rules>
            <rule name="Route the requests for backend app" stopProcessing="true">
                <match url="^app/(.*)" />
                <conditions>
                    <add input="{CACHE_URL}" pattern="^(https?)://" />
                </conditions>
                <action type="Rewrite" url="{C:1}://internal.app/{R:1}" />
                <serverVariables>
                    <set name="HTTP_ACCEPT_ENCODING" value="" />
                </serverVariables>
            </rule>
        </rules>
        <outboundRules>
            <rule name="RewriteBackendAbsoluteUrlsInResponse" preCondition="ResponseIsHtml1">
                <match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^http(s)?://internal.app(\:80)?/(.*)" />
                <action type="Rewrite" value="/app/{R:3}" />
            </rule>
            <rule name="RewriteBackendAbsoluteUrlsInRedirects" preCondition="ResponseIsHtml1">
                <match serverVariable="RESPONSE_LOCATION" pattern="^http(s)?://internal.app(\:80)?/(.*)" />
                <action type="Rewrite" value="/app/{R:3}" />
            </rule>
            <rule name="RewriteBackendRelativeUrlsInResponse" preCondition="ResponseIsHtml1">
                <match filterByTags="A, Area, Base, Form, Frame, Head, IFrame, Img, Input, Link, Script" pattern="^/(.*)" negate="false" />
                <conditions>
                    <add input="{URL}" pattern="^/app/.*" />
                </conditions>
                <action type="Rewrite" value="/app/{R:1}" />
            </rule>
            <rule name="RewriteBackendRelativeUrlsInRedirects" preCondition="ResponseIsHtml1">
                <match serverVariable="RESPONSE_LOCATION" pattern="^/(.*)" negate="false" />
                <conditions>
                    <add input="{URL}" pattern="^/app/.*" />
                </conditions>
                <action type="Rewrite" value="/app/{R:1}" />
            </rule>
            <preConditions>
                <preCondition name="ResponseIsHtml1">
                    <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                </preCondition>
            </preConditions>
        </outboundRules>
    </rewrite>
    <urlCompression dynamicCompressionBeforeCache="false" />
</system.webServer>

问题是,只要我停止清除HTTP_ACCEPT_ENCODING服务器变量,与上述规则相匹配的每个请求都以以下错误结束:HTTP Error 500.52 - URL Rewrite Module Error. Outbound rewrite rules cannot be applied when the content of the HTTP response is encoded ("gzip").

我知道这个线程,我遵循这些指示。我已经设置dynamicCompressionBeforeCache="false"为可以在上面看到,我已经添加了必要的注册表项,并且我确信这些模块在IIS中的顺序是正确的。

但是,这似乎只有在重写发生在一个Web应用程序中才有效。如果我删除上面的规则并添加一个简单的规则(和相应的出站规则)来重写(例如)/x/WHATEVER,只需完成/WHATEVER所有工作而不需要清除HTTP_ACCEPT_ENCODING- 规则将起作用,并且对重写的请求启用压缩。

但是,只要我重新添加了我的规则,该规则将响应重写为不同的Web应用程序,并且我没有清除HTTP_ACCEPT_ENCODING标题,则会再次出现相同的错误。

根据我的理解,如果重写涉及另一个Web应用程序,那么对于可以完成的事情有更多的限制。例如,URL重写器必须从后端服务器接收未压缩的响应,以便能够使用出站规则重写它。我想HTTP_ACCEPT_ENCODING在这种情况下清理是必须的,因为这一点。

但是我期望,因为压缩模块列在模块列表的顶部,所以最终重写的响应应该被压缩,不管它来自哪里。看起来IIS做出了一些快捷方式,并将响应返回给绕过压缩模块的客户端。或者HTTP_ACCEPT_ENCODING很快移除标题以完全禁用压缩(不仅在服务器到服务器通信中)。

最后,我的问题是:是否有办法压缩这些回应?

提问于
用户回答回答于

我已经想出了自己。

需要做些什么来实现它的工作:

  • Accept-Encoding 在将请求路由到后端服务器之前,必须删除头,以便可以使用出站规则重写该响应
  • 报头必须通过附加的出站规则进行恢复,以便在响应发送到客户端之前压缩模块启动时出现该报头

我决定这样做:

  • 将新的服务器变量添加到重写规则中,以保存客户端发送的原始头文件: <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" /> (我把它放在清除HTTP_ACCEPT_ENCODING变量的那一行之前)
  • 添加新的出站规则: <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding"> <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" /> <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" /> </rule> 并附带前提条件: <preCondition name="NeedsRestoringAcceptEncoding"> <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" /> </preCondition>

热门问答

腾讯会议共享屏幕,其他人收到的是黑屏?

腾讯云音视频 支持 移动端h5吗( 不是小程序的)?

shixin

腾讯 · 高级产品经理 (已认证)

推荐

实时音视频TRTC的Web版是基于WebRTC的方案,需要浏览器的对WebRTC的支持,支持WebRTC的浏览器就可以。但是,移动端浏览器对WebRTC支持的情况并不好,建议使用小程序版。

腾讯云IoT物联平台中如何自定义Topic?

DylanRichard

腾讯 · 产品经理 (已认证)

万物互联的时代,欢迎来到IoT的世界
推荐已采纳
第二个是物联网通信平台(IoT Hub)的,https://cloud.tencent.com/document/product/634/32546。目前物联网开发平台(IoT explorer)只支持基于数据模板协议的接入(文档 https://cloud.tencent.co...... 展开详请

如何用命令修改腾讯云解析目标ip?

氧化先生道可道 非常道 名可名 非常名
推荐
可以,参考: https://cns.api.qcloud.com/v2/index.php? &<公共请求参数> &Action=RecordCreate &domain=qcloud.com &subDomain=www &recordType=A &recordLine=默...... 展开详请

组队匹配完整流程是怎样的?感觉缺少API支持?

您好,matchgroup匹配成功后,小组成员会进入同一个房间和同一个队伍,这个API需要传玩家ID,通过邀请好友进房间就能拿到玩家的id,解散房间后再调用matchgroup,在没有解散房间不能调用matchGroup 接口。

SCF使用了k8s或docker容器技术吗?

Mason-Serverless

腾讯 · 产品经理 (已认证)

推荐

SCF的新架构使用的轻量化虚拟机技术,同时MVM里内嵌的有docker,但是没有使用K8S

所属标签

扫码关注云+社区

领取腾讯云代金券