Apache-2.2
http請求的gzip不正確,找不到是誰在做的
我們看到一些非常奇怪的 HTTP 響應混亂,我們無法弄清楚這是怎麼回事。我們有一個處理 JSON 請求的應用伺服器。有時,返回的響應是 gzip 壓縮的,但帶有不正確的標頭,這會阻止瀏覽器正確解釋它。
這個問題是間歇性的,並且隨著時間的推移會改變行為。昨天早上,它似乎有 50% 的時間都失敗了,事實上,它似乎與我們的兩台負載平衡伺服器中的一台有關。下午晚些時候,它在 1000 次中只有 20 次失敗,並且與應用伺服器無關。
兩個應用伺服器執行 Apache 2.2,帶有 mod_wsgi 和 Django 應用堆棧。它們具有相同的 Apache 配置和原始碼樹,甚至在 Red Hat 上安裝了相同的軟體包。前面有一個硬體負載均衡器,我不知道品牌或型號。
Akamai 也是食物鏈的一部分,儘管我們移除了 Akamai,但問題仍然存在。
這是一個很好的請求和響應:
* Connected to example.com (97.7.79.129) port 80 (#0) > POST /claim/ HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15 > Host: example.com > Accept: */* > Referer: http://example.com/apps/ > Accept-Encoding: gzip,deflate > Content-Length: 29 > Content-Type: application/x-www-form-urlencoded > } [data not shown] < HTTP/1.1 200 OK < Server: Apache/2 < Content-Language: en-us < Content-Encoding: identity < Content-Length: 47 < Content-Type: application/x-javascript < Connection: keep-alive < Vary: Accept-Encoding < { [data not shown] * Connection #0 to host example.com left intact * Closing connection #0 {"msg": "", "status": "OK", "printer_name": ""}
這是一個壞的:
* Connected to example.com (97.7.79.129) port 80 (#0) > POST /claim/ HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15 > Host: example.com > Accept: */* > Referer: http://example.com/apps/ > Accept-Encoding: gzip,deflate > Content-Length: 29 > Content-Type: application/x-www-form-urlencoded > } [data not shown] < HTTP/1.1 200 OK < Server: Apache/2 < Content-Language: en-us < Content-Encoding: identity < Content-Type: application/x-javascript < Content-Encoding: gzip < Content-Length: 59 < Connection: keep-alive < Vary: Accept-Encoding < X-N: S < { [data not shown] * Connection #0 to host example.com left intact * Closing connection #0 �V�-NW�RPR�QP*.I,)-���A���̼�Ԣ����T��Z� ��/
不良反應有兩點需要注意:
- 它有兩個 Content-Encoding 標頭,瀏覽器似乎使用第一個。因此他們看到了一個身份編碼標頭和壓縮的內容,因此他們無法解釋響應。
- 錯誤響應有一個額外的“XN: S”標頭。
也許如果我能找出中間人在響應中添加了“XN:S”標題,我就可以找到罪魁禍首……
一些額外的線索
根據http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5:
- identity預設(身份)編碼;不使用任何轉換。此內容編碼僅在 Accept-Encoding 標頭中使用,不應在 Content-Encoding 標頭中使用。
Akamai 似乎忽略了這樣一個事實,即伺服器可以在其響應中包含此標頭,並且在將編碼更改為“gzip”時不會將其刪除。
由於上游伺服器“不應該”首先添加標頭,這是解決此問題的另一種方法。