強迫網頁預設編碼語系

參考網址:精讚部落格
 

瀏覽器對於網頁的語系判斷,網路上一堆文章在討論,不過我覺得不太正確,似是而非,所以我寫了這篇文章。

首先,大家都知道網頁的HEADER這行可以決定編碼方式,這個稱之為 META

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

html5
<meta charset="utf-8" />

大部分的瀏覽器如果編碼設成「自動偵測」時都能正確的分析,並以 utf-8 輸出。但世界並不會這麼平順完美,明明我這樣設定時,他就是用 big5 丟出來,或是我明明設定 META 為 big5,但是他丟出來卻是 utf-8,是不是我的瀏覽器不好,所以換了瀏覽器,也許仍不正常(或者是正常後開始罵不正常的瀏覽器爛)。

為何會如此?先來研究一下,在 APACHE 的 httpd.conf 及 php.ini 中都有指定編碼語系的方式,例如:

[httpd.conf]
AddDefaultCharset Big5

[php.ini]
default_charset = "iso-8859-1"

這個萬不得已是不應該去指定的,因為一旦指定,也許能解決一時的問題,但是未來接手管理的人,會毫無頭緒,不知道為什麼編碼怎麼設都不正確,找不出原因;或是同網站不同編碼的網頁,怎麼試都不正確。此外,如果在共用的空間中,更沒有辦法去修改 httpd.conf 或是 php.ini 的 charset,常會一個頭兩個大。

接下來我們來研究..

為什麼明明 META 就已經正確了,瀏覽器好像視而不見?

先來看看,如果在 httpd.conf 中或是php.ini 已經預設了編碼,瀏覽器取得網頁有什麼不同。這裡我們就要回到 http 這個協定一開始的定義點來看
Hypertext Transfer Protocol — HTTP/1.1 rfc 2612

瀏覽器在取得網頁內容之前,無論有無讀取過,都會進行一個 HEAD method 以檢查網頁是否有更新,以決定是否要 refresh。所以我們來看一下有定義 charset 和未定義 charset 時取回的 head 有何不同,特別注意,這個 HEAD 不是網頁裡的 < head></head>標籤中的東西,別搞錯了。

# telnet kt.example.com 80
Trying 114.33.4.124...
Connected to example.com.
Escape character is '^]'.
HEAD
 / HTTP/1.1
Host:kt.example.com
Connection: close

HTTP/1.1 200 OK
Date: Sat, 24 Apr 2010 06:44:14 GMT
Server: Apache/2.2.9 (FreeBSD) mod_ssl/2.2.9 OpenSSL/0.9.8e DAV/2 PHP/5.2.6 with Suhosin-Patch
X-Powered-By: PHP/5.2.6
Set-Cookie: PHPSESSID=v8hrfte7qvlhs8vmfeu4fgcch3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Content-Type: text/html; charset=Big5   &lt;== 注意看,多出這一行

Connection closed by foreign host.

 

由此可知,瀏覽器在 HEAD method 完畢後,就自動會切換成 Big5 的編碼,這時就算你在 <META> 中怎麼設定,瀏覽器全都視而不見啦,這和什麼 BOM 一點關係也沒有。

因為瀏覽器使用http的method,如GET、POST、HEAD…等方法去取回資料時,伺服器早就偷偷的寫說要「指定」什麼編碼來顯示,瀏覽器根本就不再理會你html中的meta指定編碼的那行。就算你怎麼設定,他就只會聽伺服器說的…

本篇發表於 Linux系統, 程式設計。將永久鏈結加入書籤。