IIS作为反向代理 - 从后端服务器改写响应的压缩(IIS as a reverse proxy -

2019-08-21 07:20发布

我采取将请求路由到后端服务器的反向代理。

功能一切正常,但我关注的是从后端服务器的所有响应传输到客户端(网页浏览器)无压缩。

设置如下:

  • 后端服务器,供公众无法访问,在内部域。 主机上的Web应用程序https://internal.app
  • 与IIS 7.5前端WEB服务器,托管主要的公共网站,充当后台服务器的代理。 主要站点是在https://site.com

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

我目前的设置是基于URL重写2.0和应用程序请求路由IIS扩展。 一般的处理方法是基于下列条款准则:

  • 设置使用IIS,URL重写和ARR反向代理
  • 反向代理与网址重写v2和应用程序请求路由

有关节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"). 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 -规则运作,并压缩了重写请求启用。

但只要我重新添加我的规则,改写为不同的网络应用程序的响应,我不清除HTTP_ACCEPT_ENCODING头,再次出现同样的错误。

据我了解,如果重写涉及到另一个Web应用程序,有什么可以做更多的约束。 例如,URL重写必须接收来自后端服务器,以未压缩的响应能够使用出站规则重写一遍。 我想清除HTTP_ACCEPT_ENCODING在这种情况下是因为这是必须的。

但是,我希望的是,由于压缩模块的模块列表的顶部列出,最后重写反应,应压缩不管它源于。 看来IIS使一些快捷键和返回给客户端绕过压缩模块的响应。 或者HTTP_ACCEPT_ENCODING移出头部很快完全禁用压缩(不仅在服务器到服务器的通信)。

所以最后,我的问题是:有没有办法来压缩这些反应?

Answer 1:

我已经想通了自己。

需要做得到它的工作是什么:

  • 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> 

工程就像一个魅力至今。



Answer 2:

为了解决楼主的问题,同时仍保留gzip压缩的反应 ,一个只需要做到以下几点:

  1. 更新您的面向公众的Web服务器这样的注册表:

    一个。 对于64位的网站,运行在具有管理员权限的命令控制台以下: reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0

    湾 对于32位的网站,运行在具有管理员权限的命令控制台以下: reg add HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432node\Microsoft\Inetstp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0

  2. 重置IIS

  3. 禁用静态压缩

    一个。 做到这一点,我插入下面我的web配置: <urlCompression doStaticCompression="false" doDynamicCompression="true" dynamicCompressionBeforeCache="false" />

  4. 在IIS管理器的服务器节点上,双击Modules图标,然后在右侧,点击“查看排序列表”,并确认您的静态/动态压缩模块朝向顶部和URL重写模块位于底部

请注意

我看到很多的决议对这一问题漂浮在HTTP_CONTENT_TYPE请求头被清理出去的URL重写规则(包括本网页上的答案)的一部分净。 每个人都应该知道,虽然这确实解决了500.52错误的原始问题,对响应gzip压缩将被删除 。 这可能是所希望的结果,但如果需要的话gzip压缩,将上述溶液就可以了



Answer 3:

PS:如果你有超过你的应用服务器控制下面的解决方案仅适用。

它基本上让Web服务器做压缩,并让应用服务器做什么样的应用程序是应该做的(不压缩)的重型。

如果应用程序服务器上禁用了压缩,从应用服务器,你得到的回应是未压缩的。 在Web服务器上,应启用压缩,因此Web服务器将信守HTTP标头“接受编码:gzip,紧缩”,而响应客户端(浏览器)。

此配置将卸载应用程序服务器上的CPU,但会增加你的Web服务器和应用服务器之间的网络流量。 如果你在内部网络上,它不会有太大的性能影响。



Answer 4:

只要添加一个“serverVariables”标签的重写规则为我做的伎俩:

<rewrite>
        <rules>
            <rule name="ReverseProxyInboundRule1" stopProcessing="true">
                <match url="(.*)" />
                <action type="Rewrite" url="http://otherurl{R:1}" />

                <serverVariables>
                    <set name="HTTP_ACCEPT_ENCODING" value="" />
                </serverVariables>
            </rule>

       </rules>
</rewrite>


文章来源: IIS as a reverse proxy - compression of rewritten response from backend server