web-dev-qa-db-ja.com

IISリバースプロキシとして-バックエンドサーバーからの書き換えられた応答の圧縮

リクエストをバックエンドサーバーにルーティングするためのリバースプロキシを実装しています。

機能的にはすべて正しく機能しますが、バックエンドサーバーからのすべての応答が圧縮されずにクライアント(Webブラウザー)に転送されるのではないかと心配しています。

セットアップは次のとおりです。

  • 内部ドメイン上のバックエンドサーバー(パブリックアクセス不可)。 _https://internal.app_でWebアプリケーションをホストします
  • IIS 7.5のフロントWebサーバー。メインのパブリックWebサイトをホストし、バックエンドサーバーのプロキシとして機能します。メインサイトは_https://site.com_にあります。

すべてのリクエストを_https://site.com/app/WHATEVER_に_https://internal.app/WHATEVER_にルーティングし、クライアントには透過的にしたい。

現在の設定は、URL Rewrite 2.0とApplication Request Routing IIS extensions)に基づいています。一般的なアプローチは、次の記事のガイドラインに基づいています。

_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").

私は this thread を認識しており、それらの指示に従いました。上記のように_dynamicCompressionBeforeCache="false"_を設定し、必要なレジストリエントリを追加して、IISでモジュールが正しい順序になっていることを確認しました。

ただし、これは1つのWebアプリ内で書き換えが発生した場合にのみ機能するようです。上記のルールを削除し、単純なルール(およびそれぞれの送信ルール)を追加して、たとえば_/x/WHATEVER_から_/WHATEVER_まで、すべてが完全に機能し、_HTTP_ACCEPT_ENCODING_をクリアする必要はありません。ルールは機能し、書き換えられたリクエストに対して圧縮が有効になります。

しかし、別のWebアプリへの応答を書き換えるルールを再度追加し、_HTTP_ACCEPT_ENCODING_ヘッダーをクリアしないと、同じエラーが再び表示されます。

私が理解しているところによると、書き換えが別のWebアプリに関係している場合、何ができるかに制約があります。例えば。 URLリライタは、アウトバウンドルールを使用してリライトできるようにするために、バックエンドサーバーから非圧縮応答を受信する必要があります。このため、このシナリオでは_HTTP_ACCEPT_ENCODING_をクリアする必要があります。

ただし、圧縮モジュールはモジュールリストの一番上にあるので、最終的に書き換えられた応答は、それがどこから来たかに関係なく圧縮されるはずです。 IISはいくつかのショートカットを作成し、圧縮モジュールをバイパスしてクライアントに応答を返します。または、_HTTP_ACCEPT_ENCODING_ヘッダーが削除されて完全に圧縮が完全に無効になります(サーバーから-サーバー通信)。

最後に、私の質問は、これらの応答を圧縮する方法はありますか?

20

私はそれを自分で理解しました。

それを機能させるために必要なこと:

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

これまでのところ魅力のように動作します。

25

gzip圧縮された応答を維持しながら元の投稿者の問題に対処するには、次の手順を実行するだけです。

  1. 次のように、公開Webサーバーのレジストリを更新します。

    a。 64ビットWebサイトの場合は、管理者権限を持つコマンドコンソールで次を実行します:reg add HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0

    b。 32ビットのWebサイトの場合は、管理者権限を持つコマンドコンソールで次を実行します:reg add HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432node\Microsoft\Inetstp\Rewrite /v LogRewrittenUrlEnabled /t REG_DWORD /d 0

  2. iISをリセットする

  3. 静的圧縮を無効にする

    a。これを達成するために、次のウェブ設定を挿入しました:<urlCompression doStaticCompression="false" doDynamicCompression="true" dynamicCompressionBeforeCache="false" />

  4. IISマネージャーのサーバーノードで、Modulesアイコンをダブルクリックし、右側にある[順序付きリストの表示]をクリックして、静的/動的圧縮モジュールが上に向かって、URL書き換えモジュールは下に向かって

ご注意ください

この問題に対する多くの解決策が、HTTP_CONTENT_TYPEリクエストヘッダーがURL書き換えルール(このページの回答を含む)の一部としてクリアされているネット上に浮かんでいます。これは500.52エラーの元の問題を解決しますが、応答のgzip圧縮は[〜#〜] removed [〜#〜]であることに注意してください。これは望ましい結果かもしれませんが、gzip圧縮が必要な場合は、上記の解決策でうまくいきます

2
Scot

PS:以下の解決策は、アプリサーバーを制御できる場合にのみ機能します。

これは基本的に、Webサーバーに圧縮を行わせ、アプリサーバーにアプリの本来の機能(圧縮なし)の大きな任務を任せます。

アプリサーバーで圧縮を無効にすると、アプリサーバーから取得する応答は圧縮されません。 Webサーバーでは、圧縮を有効にする必要があります。これにより、Webサーバーはクライアント(ブラウザー)に応答するときにHTTPヘッダー "Accept-Encoding:gzip、deflate"を受け入れます。

この構成では、アプリサーバーのCPUの負荷が軽減されますが、Webサーバーとアプリサーバー間のネットワークトラフィックが増加します。内部ネットワークを使用している場合、パフォーマンスへの影響はあまりありません。

1
Gunawan Deng

書き換えルールに「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>
1
Marcio Fonseca