IE6 不支持HTTP協議的動態壓縮chunked方式

臨近端午節放假前夕,準備上線一個項目的登錄和註冊功能,判斷用戶登錄是否成功是通過詢問一個登錄服務器login.baofeng.net,訪問方式如下:

//檢測是否登錄;
function isLoginIn(fn, i) {
if(cookie.get("LoginIn") == 1) {
showBannerUserInfo();
} else {
var url = "http://login.baofeng.net/?a=checklogin&info=1&callback=" + fn + "&reqid=" + i;
jsonRequest(url);
}
};

//檢測登錄回調
function checkLoginIn(j, i) {
if(j.status == 1) {
cookie.put("LoginIn", 1); //1表示登錄
cookie.put("bf_sid", j.bf_sid); //存bf_sid
cookie.put("username", j.userinfo.username);
cookie.put("email", j.userinfo.email);
showBannerUserInfo();
} else {
showBannerUserLogin();
}
};


可是在上線時,一件奇怪的事情發生了,內測服務器都OK的功能,放到外網服務器就在IE6瀏覽器出現問題。


排除法:

將外網服務器的代碼全部搬移到內網測試服務器上,功能全部OK,再放到線上服務器,還是出問題。

衆人拾材火焰高:

本着沒病不死人的原則,大家繼續定位問題,發現當前這個腳本的JS沒有完全加載完成,加載到某一段就斷掉了,發現問題就似乎有了一線生機,通過抓包工具發現當前這個base.js的返回code是200,但沒有Content-Length的值,奇怪爲什麼服務器會不返回這個值呢。通過搜索得知爲了提高網頁展現的性能,Nginx服務器提供了Gzip模塊,該模塊採用動態壓縮chunked方式提高網頁返回的效率,服務器的nginx的配置如下:

#開啓gzip模塊,要求安裝gzip 在運行./config時要指定
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
output_buffers 1 32k;
postpone_output 1460;



上述模塊的參數說明:[url=http://www.5gme.com/space-6-do-blog-id-57096.html]http://www.5gme.com/space-6-do-blog-id-57096.html[/url]


通過反覆測試終於發現了這個問題的真正原因:

本次功能新增的一臺登錄驗證服務器也是採用Nginx對外提供登錄確認的服務,該服務也是同樣採取的gzip模塊進行壓縮,將此服務器的gzip模塊註銷掉,IE6下不能判定登錄註冊狀態的問題解決了。


通常,HTTP協議中使用Content-Length這個頭來告知數據的長度。然後,在數據下行的過程中,Content-Length的方式要預先在服務器中緩存所有數據,然後所有數據再一股腦兒地發給客戶端。

如果要一邊產生數據,一邊發給客戶端,WEB 服務器就需要使用"Transfer-Encoding: chunked"這樣的方式來代替Content-Length。


"Transfer-Encoding: chunked"是這樣編碼的:

HTTP頭
\r\n
\r\n --連續的兩個\r\n之後就是HTTP體了
16進制值代表的數據長度
\r\n
上面所指的數據長度
\r\n --每段數據結束後,以\r\n標識

16進制代表的第二段數據
\r\n
XX長度的數據
\r\n

………… (反覆通過這樣的方式表示每次傳輸的數據長度)

0 --數據結束部分用0表示,然後是連續的兩個\r\n
\r\n
\r\n



由於IE6不支持chunked方式的動態壓縮,所以只能放棄對IE6用戶的壓縮,調整Nginx的配置:

#開啓gzip模塊,要求安裝gzip 在運行./config時要指定
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
gzip_disable "MSIE [1-6] \.";
output_buffers 1 32k;
postpone_output 1460;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章