[英]IIS as a reverse proxy - compression of rewritten response from backend server
我正在實現一個反向代理,用於將請求路由到后端服務器。
功能上一切正常,但是我擔心來自后端服務器的所有響應都會在沒有壓縮的情況下傳輸到客戶端(Web瀏覽器)。
設置如下:
https://internal.app
上https://internal.app
Web應用程序 https://site.com
。 我想以對客戶端透明的方式將所有請求路由到https://site.com/app/WHATEVER
到https://internal.app/WHATEVER
。
我當前的設置基於URL Rewrite 2.0和Application Request Routing IIS擴展。 一般方法基於以下文章的指導原則:
site.com
應用程序的web.config
的相關部分:
<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
- 規則有效並且對重寫的請求啟用了壓縮。
但是,一旦我重新添加我的規則,該規則將響應重寫為其他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服務器上的注冊表:
一個。 對於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
重置IIS
禁用靜態壓縮
一個。 為了實現這一點,我插入了以下我的web配置: <urlCompression doStaticCompression="false" doDynamicCompression="true" dynamicCompressionBeforeCache="false" />
在IIS管理器的服務器節點中,雙擊“ Modules
圖標,然后在右側單擊“查看有序列表”並驗證您的靜態/動態壓縮模塊是否位於頂部,URL重寫模塊位於底部
請注意
我看到很多關於此問題的解決方案浮動在網絡上,其中HTTP_CONTENT_TYPE請求標頭被清除作為URL重寫規則的一部分(包括此頁面上的答案)。 每個人都應該知道,雖然這確實解決了500.52錯誤的原始問題,對響應gzip壓縮將被刪除 。 這可能是期望的結果,但如果需要gzip壓縮,上述解決方案就可以解決問題
PS:以下解決方案僅在您控制應用服務器時才有效。
它基本上是讓Web服務器進行壓縮,讓app服務器完成應用程序應該做的重任(無需壓縮)。
如果您在應用服務器上禁用壓縮,則從應用服務器獲得的響應將被解壓縮。 在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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.