十二月 3rd, 2009歸檔于:文摘翻譯讀
書筆記Tag: Internet, web 非常感謝 @ytzong同學在twitter上推薦這篇文章,原文在此。 本文系統(tǒng)的對HTTP Headers進行了簡明易懂的闡述,我僅稍作筆記。 什么是HTTP HeadersHTTP是“Hypertext Transfer Protocol”的所寫,整個萬維網都在使用這種協(xié)議,幾乎你在瀏覽器里看到的大部分內容都是通過http協(xié)議來傳輸?shù)?,比如這篇文章。 HTTP Headers是HTTP請求和相應的核心,它承載了關于客戶端瀏覽器,請求頁面,服務器等相關的信息。 示例當你在瀏覽器地址欄里鍵入一個url,你的瀏覽器將會類似如下的http請求: 請求完成之后,你的瀏覽器可能會收到如下的HTTP響應:
第一行呢被稱為“Status Line”,它之后就是http headers,空行完了就開始輸出內容了(在這個案例中是一些html輸出)。 但你查看頁面源代碼卻不能看到HTTP headers,雖然它們同你能看到的東西一起被傳送至瀏覽器了。 這個HTTP請求也發(fā)出了一些其它資源的接收請求,例如圖片,css文件,js文件等等。 下面我們來看看細節(jié)。 怎樣才能看到HTTP Headers下面這些FireFox擴展能夠幫助你分析HTTP headers: 1. firebug 3. 在PHP中:
文章下面將會看到一些使用php示范的例子。 HTTP Request 的結構被稱作“first line”的第一行包含三個部分:
剩下的部分每行都是一個“Name:Value”對。它們包含了各式各樣關于請求和你瀏覽器的信息。例如”User-Agent“就表明了你瀏覽器 版本和你所用的操作系統(tǒng)?!盇ccept-Encoding“會告訴服務器你的瀏覽可以接受類似gzip的壓縮輸出。 這些headers大部分都是可選的。HTTP 請求甚至可以被精簡成這樣子:
并且你仍舊可以從服務器收到有效的響應。 請求類型三種最常見的請求類型是:GET,POST 和 HEAD ,從html的編寫過程中你可能已經熟悉了前兩種。 GET:獲取一個文檔大部分被傳輸?shù)綖g覽器的html,images,js,css, … 都是通過GET方法發(fā)出請求的。它是獲取數(shù)據(jù)的主要方法。 例如,要獲取Nettuts+ 的文章,http request的第一行通??雌饋硎沁@樣的:
一旦html加載完成,瀏覽器將會發(fā)送GET 請求去獲取圖片,就像下面這樣:
表單也可以通過GET方法發(fā)送,下面是個例子:
當這個表單被提交時,HTTP request 就會像這樣:
你可以將表單輸入通過附加進查詢字符串的方式發(fā)送至服務器。 POST:發(fā)送數(shù)據(jù)至服務器盡管你可以通過GET方法將數(shù)據(jù)附加到url中傳送給服務器,但在很多情況下使用POST發(fā)送數(shù)據(jù)給服務器更加合適。通過GET發(fā)送大量數(shù)據(jù)是不現(xiàn) 實的,它有一定的局限性。 用POST請求來發(fā)送表單數(shù)據(jù)是普遍的做法。我們來吧上面的例子改造成使用POST方式:
提交這個表單會創(chuàng)建一個如下的HTTP 請求:
這里有三個需要注意的地方:
POST方式的請求也可用在AJAX,應用程序,cURL … 之上。并且所有的文件上傳表單都被要求使用POST方式。 HEAD:接收頭部信息HEAD和GET很相似,只不過HEAD不接受HTTP響應的內容部分。當你發(fā)送了一個HEAD請求,那就意味著你只對HTTP頭部感興趣,而不是 文檔本身。 這個方法可以讓瀏覽器判斷頁面是否被修改過,從而控制緩存。也可判斷所請求的文檔是否存在。 例如,假如你的網站上有很多鏈接,那么你就可以簡單的給他們分別發(fā)送HEAD請求來判斷是否存在死鏈,這比使用GET要快很多。 http響應結構當瀏覽器發(fā)送了HTTP請求之后,服務器就會通過一個HTTP response來響應這個請求。如果不關心內容,那么這個請求看起來會是這樣的: 第一個有價值的信息就是協(xié)議。目前服務器都會使用 HTTP/1.x 或者 HTTP/1.1。 接下來一個簡短的信息代表狀態(tài)。代碼200意味著我們的請求已經發(fā)送成功了,服務器將會返回給我們所請求的文檔,在頭部信息之后。 我們都見過“404”頁面。當我向服務器請求一個不存在的路徑時,服務器就用用404來代替200響應我們。 余下的響應內容和HTTP請求相似。這些內容是關于服務器軟件的,頁面/文件何時被修改過,mime type 等等… 同樣,這些頭部信息也是可選的。 HTTP狀態(tài)碼
200 成功 (OK) 前文已經提到,200是用來表示請求成功的。 206 部分內容 (Partial Content) 如果一個應用只請求某范圍之內的文件,那么就會返回206. 這通常被用來進行下載管理,斷點續(xù)傳或者文件分塊下載。 404 沒有找到 (Not Found) 很容易理解 401 未經授權 (Unauthorized) 受密碼保護的頁面會返回這個狀態(tài)。如果你沒有輸入正確的密碼,那么你就會在瀏覽器中看到如下的信息: 注意這只是受密碼保護頁面,請求輸入密碼的彈出框是下面這個樣子的: 403 被禁止(Forbidden) 如果你沒有權限訪問某個頁面,那么就會返回403狀態(tài)。這種情況通常會發(fā)生在你試圖打開一個沒有index頁面的文件夾。如果服務器設置不允許查看 目錄內容,那么你就會看到403錯誤。 其它一些一些方式也會發(fā)送權限限制,例如你可以通過IP地址進行阻止,這需要一些htaccess的協(xié)助。
302(或307)臨時移動(Moved Temporarily) 和 301 永久移動(Moved Permanently) 這兩個狀態(tài)會出現(xiàn)在瀏覽器重定向時。例如,你使用了類似 bit.ly 的網址縮短服務。這也是它們如何獲知誰點擊了他們鏈接的方法。 302和301對于瀏覽器來說是非常相似的,但對于搜索引擎爬蟲就有一些差別。打個比方,如果你的網站正在維護,那么你就會將客戶端瀏覽器用302 重定向到另外一個地址。搜索引擎爬蟲就會在將來重新索引你的頁面。但是如果你使用了301重定向,這就等于你告訴了搜索引擎爬蟲:你的網站已經永久的移動 到了新的地址。 500 服務器錯誤(Internal Server Error) 這個代碼通常會在頁面腳本崩潰時出現(xiàn)。大部分CGI腳本都不會像PHP那樣輸出錯誤信息給瀏覽器。如果出現(xiàn)了致命的錯誤,它們只會發(fā)送一個500的 狀態(tài)碼。這時需要查看服務器錯誤日志來排錯。 完整的列表 你可以在這里找到完整的HTTP 狀態(tài)碼說明。 HTTP Headers 中的 HTTP請求現(xiàn)在我們來看一些在HTTP headers中常見的HTTP請求信息。 所有這些頭部信息都可以在PHP的$_SERVER數(shù)組中找到。你也可以用getallheaders()函數(shù)一次性獲取所有的頭部信息。 Host一個HTTP請求會發(fā)送至一個特定的IP地址,但是大部分服務器都有在同一IP地址下托管多個網站的能力,那么服務器必須知道瀏覽器請求的是哪個域 名下的資源。
這只是基本的主機名,包含域名和子級域名。 在PHP中,可以通過$_SERVER['HTTP_HOST'] 或 $_SERVER['SERVER_NAME']來查看。 User-Agent
這個頭部可以攜帶如下幾條信息:
這就是某些網站用來收集訪客信息的一般手段。例如,你可以判斷訪客是否在使用手機訪問你的網站,然后決定是否將他們引導至一個在低分辨率下表現(xiàn)良好 的移動網站。 在PHP中,可以通過 $_SERVER['HTTP_USER_AGENT'] 來獲取User-Agent
Accept-Language
這個信息可以說明用戶的默認語言設置。如果網站有不同的語言版本,那么就可以通過這個信息來重定向用戶的瀏覽器。 它可以通過逗號分割來攜帶多國語言。第一個會是首選的語言,其它語言會攜帶一個“q”值,來表示用戶對該語言的喜好程度(0~1)。 在PHP中用 $_SERVER["HTTP_ACCEPT_LANGUAGE"] 來獲取這一信息。
Accept-Encoding
大部分的現(xiàn)代瀏覽器都支持gzip壓縮,并會把這一信息報告給服務器。這時服務器就會壓縮過的HTML發(fā)送給瀏覽器。這可以減少近80%的文件大 小,以節(jié)省下載時間和帶寬。 在PHP中可以使用 $_SERVER["HTTP_ACCEPT_ENCODING"] 獲取該信息。 然后調用ob_gzhandler()方 法時會自動檢測該值,所以你無需手動檢測。
If-Modified-Since如果一個頁面已經在你的瀏覽器中被緩存,那么你下次瀏覽時瀏覽器將會檢測文檔是否被修改過,那么它就會發(fā)送這樣的頭部:
如果自從這個時間以來未被修改過,那么服務器將會返回“304 Not Modified”,而且不會再返回內容。瀏覽器將自動去緩存中讀取內容 在PHP中,可以用$_SERVER['HTTP_IF_MODIFIED_SINCE'] 來檢測。
還有一個叫Etag的HTTP頭信息,它被用來確定緩存的信息是否正確,稍后我們將會解釋它。 Cookie顧名思義,他會發(fā)送你瀏覽器中存儲的Cookie信息給服務器。
它是用分號分割的一組名值對。Cookie也可以包含session id。 在PHP中,單一的Cookie可以訪問$_COOKIE數(shù)組獲得。你可以直接用$_SESSION array獲取session變量。如果你需要session id,那么你可以使用session_id()函數(shù)代替cookie。
Referer顧名思義, 頭部將會包含referring url信息。 例如,我訪問Nettuts+的主頁并點擊了一個鏈接,這個頭部信息將會發(fā)送到瀏覽器: 在PHP中,可以通過 $_SERVER['HTTP_REFERER'] 獲取該值。
You may have noticed the word “referrer” is misspelled as “referer”. Unfortunately it made into the official HTTP specifications like that and got stuck. Authorization當一個頁面需要授權,瀏覽器就會彈出一個登陸窗口,輸入正確的賬號后,瀏覽器會發(fā)送一個HTTP請求,但此時會包含這樣一個頭部:
包含在頭部的這部分信息是base64 encoded。例如,base64_decode(’bXl1c2VyOm15cGFzcw==’) 會被轉化為 ‘myuser:mypass’ 。 在PHP中,這個值可以用$_SERVER['PHP_AUTH_USER'] 和 $_SERVER['PHP_AUTH_PW'] 獲得。 更多細節(jié)我們會在WWW-Authenticate部分講解。 HTTP Headers 中的 HTTP響應現(xiàn)在讓我了解一些常見的HTTP Headers中的HTTP響應信息。 在PHP中,你可以通過 header()來設置頭部響應信息。PHP已經自動發(fā)送了一些必要的頭部信息,如 載入的內容,設置 cookies 等等… 你可以通過 headers_list()函數(shù)看到已發(fā)送和將要發(fā)送的頭部信息。你也可以使用headers_sent()函 數(shù)來檢查頭部信息是否已經被發(fā)送。 Cache-Control的定義是:“The Cache-Control general-header field is used to specify directives which MUST be obeyed by all caching mechanisms along the request/response chain.” 其中“caching mechanisms” 包含一些你ISP可能會用到的 網關和代理信息。 例如:
“public”意味著這個響應可以被任何人緩存,“max-age” 則表明了該緩存有效的秒數(shù)。允許你的網站被緩存降大大減少下載時間和帶寬,同時也提高的瀏覽器的載入速度。 也可以通過設置 “no-cache” 指令來禁止緩存:
Content-Type這個頭部包含了文檔的”mime-type”。瀏覽器將會依據(jù)該參數(shù)決定如何對文檔進行解析。例如,一個html頁面(或者有html輸出的php 頁面)將會返回這樣的東西:
‘text’ 是文檔類型,‘html’則是文檔子類型。 這個頭部還包括了更多信息,例如 charset。 如果是一個圖片,將會發(fā)送這樣的響應:
瀏覽器可以通過mime-type來決定使用外部程序還是自身擴展來打開該文檔。如下的例子降調用Adobe Reader:
直接載入,Apache通常會自動判斷文檔的mime-type并且添加合適的信息到頭部去。并且大部分瀏覽器都有一定程度的容錯,在頭部未提供或 者錯誤提供該信息的情況下它會去自動檢測mime-type。 你可以在這里找到一個常用mime-type列表。 在PHP中你可以通過 finfo_file()來檢測文件的ime-type。 Content-Disposition這個頭部信息將告訴瀏覽器打開一個文件下載窗口,而不是試圖解析該響應的內容。例如:
他會導致瀏覽器出現(xiàn)這樣的對話框: 注意,適合它的Content-Type頭信息同時也會被發(fā)送
Content-Length當內容將要被傳輸?shù)綖g覽器時,服務器可以通過該頭部告知瀏覽器將要傳送文件的大?。╞ytes)。
對于文件下載來說這個信息相當?shù)挠杏?。這就是為什么瀏覽器知道下載進度的原因。 例如,這里我寫了一段虛擬腳本,來模擬一個慢速下載。
結果將會是這樣的: 現(xiàn)在,我將Content-Length頭部注釋掉:
結果就變成了這樣: 這個瀏覽器只會告訴你已下載了多少,但不會告訴你總共需要下載多少。而且進度條也不會顯示進度。 Etag這是另一個為緩存而產生的頭部信息。它看起來會是這樣:
服務器可能會將該信息和每個被發(fā)送文件一起響應給瀏覽器。該值可以包含文檔的最后修改日期,文件大小或者文件校驗和。瀏覽 會把它和所接收到的文檔一起緩存。下一次當瀏覽器再次請求同一文件時將會發(fā)送如下的HTTP請求:
如果所請求的文檔Etag值和它一致,服務器將會發(fā)送304狀態(tài)碼,而不是2oo。并且不返回內容。瀏覽器此時就會從緩存加載該文件。 Last-Modified顧名思義,這個頭部信息用GMT格式表明了文檔的最后修改時間:
它提供了另一種緩存機制。瀏覽器可能會發(fā)送這樣的請求:
在If-Modified-Since一節(jié)我們已經討論過了。 Location這個頭部是用來重定向的。如果響應代碼為 301 或者 302 ,服務器就必須發(fā)送該頭部。例如,當你訪問 http://www. 時瀏覽器就會收到如下的響應:
在PHP中你可以通過這種方式對訪客重定向: 默認會發(fā)送302狀態(tài)碼,如果你想發(fā)送301,就這樣寫:
Set-Cookie當一個網站需要設置或者更新你瀏覽的cookie信息時,它就會使用這樣的頭部:
每個cookie會作為單獨的一條頭部信息。注意,通過js設置cookie將不會體現(xiàn)在HTTP頭中。 在PHP中,你可以通過setcookie()函 數(shù)來設置cookie,PHP會發(fā)送合適的HTTP 頭。
它會發(fā)送這樣的頭信息:
如果未指定到期時間,cookie就會在瀏覽器關閉后被刪除。 WWW-Authenticate一個網站可能會通過HTTP發(fā)送這個頭部信息來驗證用戶。當瀏覽器看到頭部有這個響應時就會打開一個彈出窗。
它會看起來像這樣: 在PHP手冊的一章中就有一段簡單的代碼演示了如果用PHP做這樣的事情:
Content-Encoding這個頭部通常會在返回內容被壓縮時設置。
在PHP中,如果你調用了ob_gzhandler()函 數(shù),這個頭部將會自動被設置。 |
|