一、http頭引入:
正确的設定http頭部資訊有助于搜尋引擎判斷網頁及提升網站通路速度。通常http消息包括:客戶機向伺服器的請求消息和伺服器向客戶機的響應消息。用戶端向伺服器發送一個請求,請求頭包含請求的方法、uri、協定版本、以及包含請求修飾符、客戶資訊和内容的類似于mime的消息結構。伺服器以一個狀态行作為響應,相應的内容包括消息協定的版本,成功或者錯誤編碼加上包含伺服器資訊、實體元資訊以及可能的實體内容。

http協定定義了很多與伺服器互動的方法,即http請求的種類中,最基本的有4種,分别是get、post、put、delete。一個url位址用于描述一個網絡上的資源,而http中get、post、put、 delete就對應着對這個資源的查、改、增、删4個操作,我們最常見的就是get和post了。
get:通過請求uri得到資源。一般用于擷取/查詢資源資訊。
post:用于向伺服器送出新的内容。一般用于更新資源資訊。
二、http頭資訊解讀:
http的頭域包括通用頭、請求頭、響應頭和實體頭四個部分。每個頭域由一個域名,冒号(:)和域值三部分組成(說白了就是鍵值對)。
通用頭:是用戶端和伺服器都可以使用的頭部,可以在用戶端、伺服器和其他應用程式之間提供一些非常有用的通用功能,如date頭部。
請求頭:是請求封包特有的,它們為伺服器提供了一些額外資訊,比如用戶端希望接收什麼類型的資料,如accept頭部。
響應頭:便于用戶端提供資訊,比如,客服端在與哪種類型的伺服器進行互動,如server頭部。
實體頭:指的是用于應對實體主體部分的頭部,比如,可以用實體頭部來說明實體主體部分的資料類型,如content-type頭部。
三、http通用頭:
通用頭域包含請求和響應消息都支援的頭域,通用頭域包含緩存頭部cache-control、pragma及資訊性頭部connection、date、transfer-encoding、update、via。
1、cache-control
cache-control指定請求和響應遵循的緩存機制。在請求消息或響應消息中設定 cache-control并不會修改另一個消息處理過程中的緩存處理過程。請求時的緩存指令包括no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached,響應消息中的指令包括public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。各個消息中的指令含義如下:
no-cache:訓示請求或響應消息不能緩存,實際上是可以存儲在本地緩存區中的,隻是在與原始伺服器進行新鮮度驗證之前,緩存不能将其提供給用戶端使用。
no-store:緩存應該盡快從存儲器中删除文檔的所有痕迹,因為其中可能會包含敏感資訊。
max-age:緩存無法傳回緩存時間長于max-age規定秒的文檔,若不超規定秒浏覽器将不會發送對應的請求到伺服器,資料由緩存直接傳回;超過這一時間段才進一步由伺服器決定是傳回新資料還是仍由緩存提供。若同時還發送了max-stale指令,則使用期可能會超過其過期時間。
min-fresh:至少在未來規定秒内文檔要保持新鮮,接受其新鮮生命期大于其目前 age 跟 min-fresh 值之和的緩存對象。
max-stale:訓示用戶端可以接收過期響應消息,如果指定max-stale消息的值,那麼用戶端可以接收過期但在指定值之内的響應消息。
only-if-cached:隻有當緩存中有副本存在時,用戶端才會獲得一份副本。
public:訓示響應可被任何緩存區緩存,可以用緩存内容回應任何使用者。
private:訓示對于單個使用者的整個或部分響應消息,不能被共享緩存處理,隻能用緩存内容回應先前請求該内容的那個使用者。
2、pragma
pragma頭域用來包含實作特定的指令,最常用的是pragma:no-cache。在http/1.1協定中,它的含義和cache- control:no-cache相同。
3、connection
connection表示是否需要持久連接配接。如果servlet看到這裡的值為“keep-alive”,或者看到請求使用的是http 1.1(http 1.1預設進行持久連接配接),它就可以利用持久連接配接的優點,當頁面包含多個元素時(例如applet,圖檔),顯著地減少下載下傳所需要的時間。要實作這一點,servlet需要在應答中發送一個content-length頭,最簡單的實作方法是:先把内容寫入bytearrayoutputstream,然後在正式寫出内容之前計算它的大小。
close:告訴web伺服器或者代理伺服器,在完成本次請求的響應後,斷開連接配接,不要等待本次連接配接的後續請求了。
keepalive:告訴web伺服器或者代理伺服器,在完成本次請求的響應後,保持連接配接,等待本次連接配接的後續請求。
keep-alive:如果浏覽器請求保持連接配接,則該頭部表明希望 web 伺服器保持連接配接多長時間(秒),如keep-alive:300。
4、date
date頭域表示消息發送的時間,伺服器響應中要包含這個頭部,因為緩存在評估響應的新鮮度時要用到,其時間的描述格式由rfc822定義。例如,date:mon, 31 dec 2001 04:25:57 gmt。date描述的時間表示世界标準時,換算成本地時間,需要知道使用者所在的時區。
5、transfer-encoding
web 伺服器表明自己對本響應消息體(不是消息體裡面的對象)作了怎樣的編碼,比如是否分塊(chunked),例如:transfer-encoding: chunked
6、upgrade
它可以指定另一種可能完全不同的協定,如http/1.1用戶端可以向伺服器發送一條http/1.0請求,其中包含值為“http/1.1”的update頭部,這樣用戶端就可以測試一下伺服器是否也使用http/1.1了。
7、via
列出從用戶端到 ocs 或者相反方向的響應經過了哪些代理伺服器,他們用什麼協定(和版本)發送的請求。
當用戶端請求到達第一個代理伺服器時,該伺服器會在自己發出的請求裡面添加 via 頭部,并填上自己的相關資訊,當下一個代理伺服器 收到第一個代理伺服器的請求時,會在自己發出的請求裡面複制前一個代理伺服器的請求的via頭部,并把自己的相關資訊加到後面,以此類推,當 ocs 收到最後一個代理伺服器的請求時,檢查 via 頭部,就知道該請求所經過的路由。例如:via:1.0 236-81.d07071953.sina.com.cn:80 (squid/2.6.stable13)
四、http請求頭:
請求頭用于說明是誰或什麼在發送請求、請求源于何處,或者用戶端的喜好及能力。伺服器可以根據請求頭部給出的用戶端資訊,試着為用戶端提供更好的響應。請求頭域可能包含下列字段accept、accept-charset、accept- encoding、accept-language、authorization、from、host、if-modified-since、if-match、if-none-match、if-range、if-range、if-unmodified-since、max-forwards、proxy-authorization、range、referer、user-agent。對請求頭域的擴充要求通訊雙方都支援,如果存在不支援的請求頭域,一般将會作為實體頭域處理。
8、accept
告訴web伺服器自己接受什麼媒體類型,*/* 表示任何類型,type/* 表示該類型下的所有子類型,type/sub-type。
9、accept-charset
浏覽器告訴伺服器自己能接收的字元集。
10、accept-encoding
浏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支援壓縮,支援什麼壓縮方法(gzip,deflate)。
11、accept-language
浏覽器申明自己接收的語言。語言跟字元集的差別:中文是語言,中文有多種字元集,比如big5,gb2312,gbk等等。
12、authorization
當用戶端接收到來自web伺服器的 www-authenticate 響應時,用該頭部來回應自己的身份驗證資訊給web伺服器。
13、if-match
如果對象的 etag 沒有改變,其實也就意味著對象沒有改變,才執行請求的動作,擷取文檔。
14、if-none-match
如果對象的 etag 改變了,其實也就意味著對象也改變了,才執行請求的動作,擷取文檔。
15、if-modified-since
如果請求的對象在該頭部指定的時間之後修改了,才執行請求的動作(比如傳回對象),否則傳回代碼304,告訴浏覽器該對象沒有修改。例如:if-modified-since:thu, 10 apr 2008 09:14:42 gmt
16、if-unmodified-since
如果請求的對象在該頭部指定的時間之後沒修改過,才執行請求的動作(比如傳回對象)。
17、if-range
浏覽器告訴 web 伺服器,如果我請求的對象沒有改變,就把我缺少的部分給我,如果對象改變了,就把整個對象給我。浏覽器通過發送請求對象的etag 或者自己所知道的最後修改時間給 web 伺服器,讓其判斷對象是否改變了。總是跟 range 頭部一起使用。
18、range
浏覽器(比如 flashget 多線程下載下傳時)告訴 web 伺服器自己想取對象的哪部分。例如:range: bytes=1173546
19、proxy-authenticate
代理伺服器響應浏覽器,要求其提供代理身份驗證資訊。
20、proxy-authorization
浏覽器響應代理伺服器的身份驗證請求,提供自己的身份資訊。
21、host
用戶端指定自己想通路的web伺服器的域名/ip 位址和端口号。如host:rss.sina.com.cn
22、referer
浏覽器向web 伺服器表明自己是從哪個網頁url獲得點選目前請求中的網址/url,例如:referer:http://www.ecdoer.com/
23、user-agent
浏覽器表明自己的身份(是哪種浏覽器)。例如:mozilla/5.0 (windows nt 6.1) applewebkit/537.36 (khtml, like gecko) chrome/36.0.1985.143 safari/537.36
五、http響應頭:
響應頭向用戶端提供一些額外資訊,比如誰在發送響應、響應者的功能,甚至與響應相關的一些特殊指令。這些頭部有助于用戶端處理響應,并在将來發起更好的請求。響應頭域包含age、location、proxy-authenticate、public、retry- after、server、vary、warning、www-authenticate。對響應頭域的擴充要求通訊雙方都支援,如果存在不支援的響應頭域,一般将會作為實體頭域處理。
24、age
當代理伺服器用自己緩存的實體去響應請求時,用該頭部表明該實體從産生到現在經過多長時間了。
25、server
web 伺服器表明自己是什麼軟體及版本等資訊。例如:server:apache/2.0.61 (unix)
26、accept-ranges
web伺服器表明自己是否接受擷取其某個實體的一部分(比如檔案的一部分)的請求。bytes:表示接受,none:表示不接受。
27、vary
web伺服器用該頭部的内容告訴 cache 伺服器,在什麼條件下才能用本響應所傳回的對象響應後續的請求。假如源web伺服器在接到第一個請求消息時,其響應消息的頭部為:content-encoding: gzip; vary: content-encoding,那麼cache伺服器會分析後續請求消息的頭部,檢查其accept-encoding,是否跟先前響應的vary頭部值一緻,即是否使用相同的内容編碼方法,這樣就可以防止cache伺服器用自己cache 裡面壓縮後的實體響應給不具備解壓能力的浏覽器。例如:vary:accept-encoding。
六、http實體頭:
實體頭部提供了有關實體及其内容的大量資訊,從有關對象類型的資訊,到能夠對資源使用的各種有效的請求方法。總之,實體頭部可以告知接收者它在對什麼進行處理。請求消息和響應消息都可以包含實體資訊,實體資訊一般由實體頭域和實體組成。實體頭域包含關于實體的原資訊,實體頭包括資訊性頭部allow、location,内容頭部content-base、content-encoding、content-language、content-length、content-location、content-md5、content-range、content-type,緩存頭部etag、expires、last-modified、extension-header。
28、allow
伺服器支援哪些請求方法(如get、post等)。
29、location
表示客戶應當到哪裡去提取文檔,用于将接收端定位到資源的位置(url)上。location通常不是直接設定的,而是通過httpservletresponse的sendredirect方法,該方法同時設定狀态代碼為302。
30、content-base
解析主體中的相對url時使用的基礎url。
31、content-encoding
web伺服器表明自己使用了什麼壓縮方法(gzip,deflate)壓縮響應中的對象。例如:content-encoding:gzip
32、content-language
web 伺服器告訴浏覽器了解主體時最适宜使用的自然語言。
33、content-length
web伺服器告訴浏覽器自己響應的對象的長度或尺寸,例如:content-length: 26012
34、content-location
資源實際所處的位置。
35、content-md5
主體的md5校驗和。
36、content-range
實體頭用于指定整個實體中的一部分的插入位置,他也訓示了整個實體的長度。在伺服器向客戶傳回一個部分響應,它必須描述響應覆寫的範圍和整個實體長度。一般格式: content-range:bytes-unitspfirst-byte-pos-last-byte-pos/entity-legth。例如,傳送頭500個位元組次字段的形式:content-range:bytes0- 499/1234如果一個http消息包含此節(例如,對範圍請求的響應或對一系列範圍的重疊請求),content-range表示傳送的範圍,content-length表示實際傳送的位元組數。
37、content-type
web 伺服器告訴浏覽器自己響應的對象的類型。例如:content-type:application/xml
38、etag
就是一個對象(比如url)的标志值,就一個對象而言,比如一個html檔案,如果被修改了,其etag也會别修改,是以,etag的作用跟last-modified的作用差不多,主要供web伺服器判斷一個對象是否改變了。比如前一次請求某個html檔案時,獲得了其 etag,當這次又請求這個檔案時,浏覽器就會把先前獲得etag值發送給web伺服器,然後web伺服器會把這個etag跟該檔案的目前etag進行對比,然後就知道這個檔案有沒有改變了。
39、expires
web伺服器表明該實體将在什麼時候過期,對于過期了的對象,隻有在跟web伺服器驗證了其有效性後,才能用來響應客戶請求。是 http/1.0 的頭部。例如:expires:sat, 23 may 2009 10:02:12 gmt
40、last-modified
web伺服器認為對象的最後修改時間,比如檔案的最後修改時間,動态頁面的最後産生時間等等。例如:last-modified:tue, 06 may 2008 02:42:43 gmt
六、以百度首頁為例擷取請求頭和響應頭内容:
1、請求頭:
我們現在通過谷歌浏覽器來檢視一下請求頭:
以打開百度首頁為例,然後在谷歌浏覽器中打開“工具-開發者工具”,切換到network标簽, 然後重新整理頁面:
上圖中,打開箭頭處html格式的檔案,顯示如下:
上圖中的request headers就是我們所需要的請求頭。裡面的内容全部是鍵值對。伺服器拿到這些鍵值對後會對其進行分析。
我們再來重複一下常見請求頭鍵值對的含義:
host:www.baidu.com 本次請求通路的主機位址(虛拟主機名稱)
cache-control:no-cache 設定網頁緩存的使用方法
pragma:no-cache
accept:text/html,xxxxxx…..用戶端可以接收的資料類型(如果内容是:*/*,表示接收所有類型)
user-agent:mozilla/5.0xxxxx 主要表示用戶端類型
accept-encoding:gzip,deflate,sdch 浏覽器能夠接收的資料壓縮編碼方式(表示浏覽器能夠接收什麼格式的壓縮的資料)
accept-language:zh-cn,zh;q=0.8 浏覽器期望的接受的語言種類
accept-charset: iso-8859-1 用戶端所接收的字元集編碼
if-modified-since: tue, 11 jul 2000 18:23:51 gmt 和緩存機制相關的頭
referer: http://www.smyh.me/index.jsp 目前頁面來自哪個頁面(可能是由之前的頁面通過超連結點進到這個頁面來)
cookie
connection: close/keep-alive 請求完之後,是關閉此連接配接,還是繼續保持連接配接
date: tue, 11 jul 2013 18:23:51 gmt 目前請求的時間
注:上面的這些指的是get請求的請求頭。
2、響應頭:
我們再來看一下響應頭的内容:
常見的響應頭鍵值對的含義:
location: http://www.smyh.me/index.jsp 重定向(302+location實作重定向)
server 伺服器類型
content-encoding 伺服器目前傳回給用戶端的資料壓縮格式
content-length 傳回給用戶端的資料量的大小
content-language: zh-cn 語言種類
content-type: text/html; charset=gb2312 傳回的資料的類型、字元集編碼方式
last-modified 資源最後一次修改的時間(配合請求頭中的if-modified-since+304/307實作緩存機制)
refresh: 1;url=http://www.it315.org 隔多少秒以後,讓目前頁面去通路哪個位址(例如網頁登陸成功後,跳回原來的界面,就是用的這個頭)
content-disposition: attachment;filename=aaa.zip 和下載下傳相關,通知浏覽器以附件的形式下載下傳伺服器發送過去的資料
transfer-encoding: chunked 資料傳輸模式
set-cookie:ss=q0=5lb_nq; path=/search 和cookie相關的頭
etag: w/"83794-1208174400000" 和cookie相關的頭
expires: -1 通知浏覽器是否緩存目前資源:如果這個頭的值是一個以毫秒為機關值,則通知浏覽器緩存資源到指定的時間點;如果值是0或-1,則通知浏覽器禁止緩存
cache-control: no-cache 通知浏覽器是否緩存資源
pragma: no-cache -- 通知浏覽器是否緩存資源
注: 之是以三個頭是一個功能,是因為曆史原因。不同的浏覽器對這三個頭支援的不同,一般來說這三個頭要同時使用,以確定不同的浏覽器都能實作控制緩存的功能
connection: close/keep-alive 是否繼續保持連接配接
date: tue, 11 jul 2000 18:23:51 gmt 目前響應的時間
七、通過android代碼擷取請求頭與相應頭的内容:
在上一篇文章中,我們講到了使用httpclient發送http請求。我們将裡面的代碼重新複制一下貼出來:(省的切換回去,麻煩的很)
activity_main.xml代碼如下:
布局檔案中,我們用一個scrollview來包裹textview。借助scrollview控件的話,就可以允許我們一滾動的形式檢視螢幕外i的那部分内容。
mainactivity.java的代碼如下:(注釋比較詳細)
這段代碼要實作的功能是:使用者點選按鈕,能夠擷取百度首頁的html資料并顯示在textview當中。
現在要做的事情是:修改上方代碼中sendrequestwithhttpclient()這個方法裡面的内容:
上方代碼中,加粗部分是我們所添加的内容,用于擷取請求頭和響應頭的鍵值對内容。代碼解釋如下:
12行:通過httpget的addheader()方法手動添加一個請求頭(我們在上一段中看到的例子其實是浏覽器幫我們添加好了的,那種情況下不需要手動添加)
14行:通過httpget的getallheaders()方法擷取響應頭的内容,并用header數組接收。注意,在導入header的包時,我們選擇org.apache.http.header這個包;請求頭的每一個鍵值對都是header裡面的内容。
16至20行:周遊輸出header數組裡面的内容。
25至32行:擷取響應頭的内容,原理類似。
運作程式,點選按鈕後,在背景輸出結果如下:
這與我們在上一段中看到的許多鍵是一樣的。