リクエストをバックエンドサーバーにルーティングするためのリバースプロキシを実装しています。
機能的にはすべて正しく機能しますが、バックエンドサーバーからのすべての応答が圧縮されずにクライアント(Webブラウザー)に転送されるのではないかと心配しています。
セットアップは次のとおりです。
https://internal.app
_で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
_ヘッダーが削除されて完全に圧縮が完全に無効になります(サーバーから-サーバー通信)。
最後に、私の質問は、これらの応答を圧縮する方法はありますか?
私はそれを自分で理解しました。
それを機能させるために必要なこと:
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>
これまでのところ魅力のように動作します。
gzip圧縮された応答を維持しながら元の投稿者の問題に対処するには、次の手順を実行するだけです。
次のように、公開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
iISをリセットする
静的圧縮を無効にする
a。これを達成するために、次のウェブ設定を挿入しました:<urlCompression doStaticCompression="false" doDynamicCompression="true" dynamicCompressionBeforeCache="false" />
IISマネージャーのサーバーノードで、Modules
アイコンをダブルクリックし、右側にある[順序付きリストの表示]をクリックして、静的/動的圧縮モジュールが上に向かって、URL書き換えモジュールは下に向かって
ご注意ください
この問題に対する多くの解決策が、HTTP_CONTENT_TYPEリクエストヘッダーがURL書き換えルール(このページの回答を含む)の一部としてクリアされているネット上に浮かんでいます。これは500.52エラーの元の問題を解決しますが、応答のgzip圧縮は[〜#〜] removed [〜#〜]であることに注意してください。これは望ましい結果かもしれませんが、gzip圧縮が必要な場合は、上記の解決策でうまくいきます
PS:以下の解決策は、アプリサーバーを制御できる場合にのみ機能します。
これは基本的に、Webサーバーに圧縮を行わせ、アプリサーバーにアプリの本来の機能(圧縮なし)の大きな任務を任せます。
アプリサーバーで圧縮を無効にすると、アプリサーバーから取得する応答は圧縮されません。 Webサーバーでは、圧縮を有効にする必要があります。これにより、Webサーバーはクライアント(ブラウザー)に応答するときにHTTPヘッダー "Accept-Encoding:gzip、deflate"を受け入れます。
この構成では、アプリサーバーのCPUの負荷が軽減されますが、Webサーバーとアプリサーバー間のネットワークトラフィックが増加します。内部ネットワークを使用している場合、パフォーマンスへの影響はあまりありません。
書き換えルールに「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>