header請求頭資訊詳細介紹
https://www.byvoid.com/zhs/blog/http-keep-alive-header
HTTP協議頭部與Keep-Alive模式詳解
1、什麼是Keep-Alive模式?
我們知道HTTP協議採用“請求-應答”模式,當使用普通模式,即非KeepAlive模式時,每個請求/應答客戶和伺服器都要新建一個連線,完成 之後立即斷開連線(HTTP協議為無連線的協議);當使用Keep-Alive模式(又稱持久連線、連線重用)時,Keep-Alive功能使客戶端到服 務器端的連線持續有效,當出現對伺服器的後繼請求時,Keep-Alive功能避免了建立或者重新建立連線。
http 1.0中預設是關閉的,需要在http頭加入"Connection: Keep-Alive",才能啟用Keep-Alive;http 1.1中預設啟用Keep-Alive,如果加入"Connection: close ",才關閉。目前大部分瀏覽器都是用http1.1協議,也就是說預設都會發起Keep-Alive的連線請求了,所以是否能完成一個完整的Keep- Alive連線就看伺服器設定情況。
2、啟用Keep-Alive的優點
從上面的分析來看,啟用Keep-Alive模式肯定更高效,效能更高。因為避免了建立/釋放連線的開銷。下面是RFC 2616 上的總結:
RFC 2616 (P47)還指出:單使用者客戶端與任何伺服器或代理之間的連線數不應該超過2個。一個代理與其它伺服器或程式碼之間應該使用不超過2 * N的活躍併發連線。這是為了提高HTTP響應時間,避免擁塞(冗餘的連線並不能程式碼執行效能的提升)。
3、回到我們的問題(即如何判斷訊息內容/長度的大小?)
Keep-Alive模式,客戶端如何判斷請求所得到的響應資料已經接收完成(或者說如何知道伺服器已經發生完了資料)?我們已經知道 了,Keep-Alive模式傳送玩資料HTTP伺服器不會自動斷開連線,所有不能再使用返回EOF(-1)來判斷(當然你一定要這樣使用也沒有辦法,可 以想象那效率是何等的低)!下面我介紹兩種來判斷方法。
3.1、使用訊息首部欄位Conent-Length
故名思意,Conent-Length表示實體內容長度,客戶端(伺服器)可以根據這個值來判斷資料是否接收完成。但是如果訊息中沒有Conent-Length,那該如何來判斷呢?又在什麼情況下會沒有Conent-Length呢?請繼續往下看……
3.2、使用訊息首部欄位Transfer-Encoding
當客戶端向伺服器請求一個靜態頁面或者一張圖片時,伺服器可以很清楚的知道內容大小,然後通過Content-length訊息首部欄位告訴客戶端 需要接收多少資料。但是如果是動態頁面等時,伺服器是不可能預先知道內容大小,這時就可以使用Transfer-Encoding:chunk模式來傳輸 資料了。即如果要一邊產生資料,一邊發給客戶端,伺服器就需要使用"Transfer-Encoding: chunked"這樣的方式來代替Content-Length。
chunk編碼將資料分成一塊一塊的發生。Chunked編碼將使用若干個Chunk串連而成,由一個標明長度為0 的chunk標示結束。每個Chunk分為頭部和正文兩部分,頭部內容指定正文的字元總數(十六進位制的數字 )和數量單位(一般不寫),正文部分就是指定長度的實際內容,兩部分之間用回車換行(CRLF) 隔開。在最後一個長度為0的Chunk中的內容是稱為footer的內容,是一些附加的Header資訊(通常可以直接忽略)。 Chunk編碼的格式如下:
Chunked-Body = *<strong>chunk </strong> "0" CRLF footer CRLF chunk = chunk-size [ chunk-ext ] CRLF chunk-data CRLF hex-no-zero = <HEX excluding "0"> chunk-size = hex-no-zero *HEX chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) footer = *entity-header 即Chunk編碼由四部分組成: 1、<strong>0至多個chunk塊</strong> ,2、<strong>"0" CRLF </strong>,3、<strong>footer </strong>,4、<strong>CRLF</strong> <strong>.</strong> 而每個chunk塊由:chunk-size、chunk-ext(可選)、CRLF、chunk-data、CRLF組成。
4、訊息長度的總結
其實,上面2中方法都可以歸納為是如何判斷http訊息的大小、訊息的數量。RFC 2616 對 訊息的長度總結如下:一個訊息的transfer-length(傳輸長度)是指訊息中的message-body(訊息體)的長度。當應用了 transfer-coding(傳輸編碼),每個訊息中的message-body(訊息體)的長度(transfer-length)由以下幾種情況 決定(優先順序由高到低):
- 任何不含有訊息體的訊息(如1XXX、204、304等響應訊息和任何頭(HEAD,首部)請求的響應訊息),總是由一個空行(CLRF)結束。
- 如果出現了Transfer-Encoding頭欄位 並且值為非“identity”,那麼transfer-length由“chunked” 傳輸編碼定義,除非訊息由於關閉連線而終止。
- 如果出現了Content-Length頭欄位,它的值表示entity-length(實體長度)和transfer-length(傳輸長 度)。如果這兩個長度的大小不一樣(i.e.設定了Transfer-Encoding頭欄位),那麼將不能傳送Content-Length頭欄位。並 且如果同時收到了Transfer-Encoding欄位和Content-Length頭欄位,那麼必須忽略Content-Length欄位。
- 如果訊息使用媒體型別“multipart/byteranges”,並且transfer-length 沒有另外指定,那麼這種自定界(self-delimiting)媒體型別定義transfer-length 。除非傳送者知道接收者能夠解析該型別,否則不能使用該型別。
- 由伺服器關閉連線確定訊息長度。(注意:關閉連線不能用於確定請求訊息的結束,因為伺服器不能再發響應訊息給客戶端了。)
為了相容HTTP/1.0應用程式,HTTP/1.1的請求訊息體中必須包含一個合法的Content-Length頭欄位,除非知道伺服器相容 HTTP/1.1。一個請求包含訊息體,並且Content-Length欄位沒有給定,如果不能判斷訊息的長度,伺服器應該用用400 (bad request) 來響應;或者伺服器堅持希望收到一個合法的Content-Length欄位,用 411 (length required)來響應。
所有HTTP/1.1的接收者應用程式必須接受“chunked” transfer-coding (傳輸編碼),因此當不能事先知道訊息的長度,允許使用這種機制來傳輸訊息。訊息不應該夠同時包含 Content-Length頭欄位和non-identity transfer-coding。如果一個訊息同時包含non-identity transfer-coding和Content-Length ,必須忽略Content-Length 。
5、HTTP頭欄位總結
最後我總結下HTTP協議的頭部欄位。
- 1、 Accept:告訴WEB伺服器自己接受什麼介質型別,/ 表示任何型別,type/* 表示該型別下的所有子型別,type/sub-type。
- 2、 Accept-Charset: 瀏覽器申明自己接收的字符集 Accept-Encoding: 瀏覽器申明自己接收的編碼方法,通常指定壓縮方法,是否支援壓縮,支援什麼壓縮方法(gzip,deflate) Accept-Language:瀏覽器申明自己接收的語言 語言跟字符集的區別:中文是語言,中文有多種字符集,比如big5,gb2312,gbk等等。
- 3、 Accept-Ranges:WEB伺服器表明自己是否接受獲取其某個實體的一部分(比如檔案的一部分)的請求。bytes:表示接受,none:表示不接受。
- 4、 Age:當代理伺服器用自己快取的實體去響應請求時,用該頭部表明該實體從產生到現在經過多長時間了。
- 5、 Authorization:當客戶端接收到來自WEB伺服器的 WWW-Authenticate 響應時,用該頭部來回應自己的身份驗證資訊給WEB伺服器。
- 6、 Cache-Control:請求:no-cache(不要快取的實體,要求現在從WEB伺服器去取) max-age:(只接受 Age 值小於 max-age 值,並且沒有過期的物件) max-stale:(可以接受過去的物件,但是過期時間必須小於 max-stale 值) min-fresh:(接受其新鮮生命期大於其當前 Age 跟 min-fresh 值之和的快取物件) 響應:public(可以用 Cached 內容迴應任何使用者) private(只能用快取內容迴應先前請求該內容的那個使用者) no-cache(可以快取,但是隻有在跟WEB伺服器驗證了其有效後,才能返回給客戶端) max-age:(本響應包含的物件的過期時間) ALL: no-store(不允許快取)
- 7、 Connection:請求:close(告訴WEB伺服器或者代理伺服器,在完成本次請求的響應後,斷開連線,不要等待本次連線的後續請求了)。 keepalive(告訴WEB伺服器或者代理伺服器,在完成本次請求的響應後,保持連線,等待本次連線的後續請求)。 響應:close(連線已經關閉)。 keepalive(連線保持著,在等待本次連線的後續請求)。 Keep-Alive:如果瀏覽器請求保持連線,則該頭部表明希望 WEB 伺服器保持連線多長時間(秒)。例如:Keep-Alive:300
- 8、 Content-Encoding:WEB伺服器表明自己使用了什麼壓縮方法(gzip,deflate)壓縮響應中的物件。例如:Content-Encoding:gzip
- 9、Content-Language:WEB 伺服器告訴瀏覽器自己響應的物件的語言。
- 10、Content-Length: WEB 伺服器告訴瀏覽器自己響應的物件的長度。例如:Content-Length: 26012
- 11、Content-Range: WEB 伺服器表明該響應包含的部分物件為整個物件的哪個部分。例如:Content-Range: bytes 21010-47021/47022
- 12、Content-Type: WEB 伺服器告訴瀏覽器自己響應的物件的型別。例如:Content-Type:application/xml
- 13、ETag:就是一個物件(比如URL)的標誌值,就一個物件而言,比如一個 html 檔案,如果被修改了,其 Etag 也會別修改,所以ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 伺服器判斷一個物件是否改變了。比如前一次請求某個 html 檔案時,獲得了其 ETag,當這次又請求這個檔案時,瀏覽器就會把先前獲得的 ETag 值傳送給WEB 伺服器,然後 WEB 伺服器會把這個 ETag 跟該檔案的當前 ETag 進行對比,然後就知道這個檔案有沒有改變了。
- 14、 Expired:WEB伺服器表明該實體將在什麼時候過期,對於過期了的物件,只有在跟WEB伺服器驗證了其有效性後,才能用來響應客戶請求。是 HTTP/1.0 的頭部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT
- 15、 Host:客戶端指定自己想訪問的WEB伺服器的域名/IP 地址和埠號。例如:Host:rss.sina.com.cn
- 16、 If-Match:如果物件的 ETag 沒有改變,其實也就意味著物件沒有改變,才執行請求的動作。
- 17、 If-None-Match:如果物件的 ETag 改變了,其實也就意味著物件也改變了,才執行請求的動作。
- 18、 If-Modified-Since:如果請求的物件在該頭部指定的時間之後修改了,才執行請求的動作(比如返回物件),否則返回程式碼304,告訴瀏覽器 該物件沒有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT
- 19、 If-Unmodified-Since:如果請求的物件在該頭部指定的時間之後沒修改過,才執行請求的動作(比如返回物件)。
- 20、 If-Range:瀏覽器告訴 WEB 伺服器,如果我請求的物件沒有改變,就把我缺少的部分給我,如果物件改變了,就把整個物件給我。瀏覽器通過傳送請求物件的 ETag 或者 自己所知道的最後修改時間給 WEB 伺服器,讓其判斷物件是否改變了。總是跟 Range 頭部一起使用。
- 21、 Last-Modified:WEB 伺服器認為物件的最後修改時間,比如檔案的最後修改時間,動態頁面的最後產生時間等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT
- 22、 Location:WEB 伺服器告訴瀏覽器,試圖訪問的物件已經被移到別的位置了,到該頭部指定的位置去取。例如:Location:http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif
- 23、 Pramga:主要使用 Pramga: no-cache,相當於 Cache-Control: no-cache。例如:Pragma:no-cache
- 24、 Proxy-Authenticate: 代理伺服器響應瀏覽器,要求其提供代理身份驗證資訊。Proxy-Authorization:瀏覽器響應代理伺服器的身份驗證請求,提供自己的身份資訊。
- 25、 Range:瀏覽器(比如 Flashget 多執行緒下載時)告訴 WEB 伺服器自己想取物件的哪部分。例如:Range: bytes=1173546-
- 26、 Referer:瀏覽器向 WEB 伺服器表明自己是從哪個 網頁/URL 獲得/點選 當前請求中的網址/URL。例如:Referer:http://www.sina.com/
- 27、 Server: WEB 伺服器表明自己是什麼軟體及版本等資訊。例如:Server:Apache/2.0.61 (Unix)
- 28、 User-Agent: 瀏覽器表明自己的身份(是哪種瀏覽器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14
- 29、 Transfer-Encoding: WEB 伺服器表明自己對本響應訊息體(不是訊息體裡面的物件)作了怎樣的編碼,比如是否分塊(chunked)。例如:Transfer-Encoding: chunked
- 30、 Vary: WEB伺服器用該頭部的內容告訴 Cache 伺服器,在什麼條件下才能用本響應所返回的物件響應後續的請求。假如源WEB伺服器在接到第一個請求訊息時,其響應訊息的頭部為:Content- Encoding: gzip; Vary: Content-Encoding那麼 Cache 伺服器會分析後續請求訊息的頭部,檢查其 Accept-Encoding,是否跟先前響應的 Vary 頭部值一致,即是否使用相同的內容編碼方法,這樣就可以防止 Cache 伺服器用自己 Cache 裡面壓縮後的實體響應給不具備解壓能力的瀏覽器。例如:Vary:Accept-Encoding
- 31、 Via: 列出從客戶端到 OCS 或者相反方向的響應經過了哪些代理伺服器,他們用什麼協議(和版本)傳送的請求。當客戶端請求到達第一個代理伺服器時,該伺服器會在自己發出的請求裡面添 加 Via 頭部,並填上自己的相關資訊,當下一個代理伺服器收到第一個代理伺服器的請求時,會在自己發出的請求裡面複製前一個代理伺服器的請求的Via 頭部,並把自己的相關資訊加到後面,以此類推,當 OCS 收到最後一個代理伺服器的請求時,檢查 Via 頭部,就知道該請求所經過的路由。例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13)
=============================================================================== HTTP 請求訊息頭部例項: Host:rss.sina.com.cn User-Agent:Mozilla/5、0 (Windows; U; Windows NT 5、1; zh-CN; rv:1、8、1、14) Gecko/20080404 Firefox/2、0、0、14 Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0、9,text/plain;q=0、8,image/png,/;q=0、5 Accept-Language:zh-cn,zh;q=0、5 Accept-Encoding:gzip,deflate Accept-Charset:gb2312,utf-8;q=0、7,*;q=0、7 Keep-Alive:300 Connection:keep-alive Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW <-- Cookie If-Modified-Since:Sun, 01 Jun 2008 12:05:30 GMT Cache-Control:max-age=0 HTTP 響應訊息頭部例項: Status:OK - 200 -- 響應狀態碼,表示 web 伺服器處理的結果。 Date:Sun, 01 Jun 2008 12:35:47 GMT Server:Apache/2.0.61 (Unix) Last-Modified:Sun, 01 Jun 2008 12:35:30 GMT Accept-Ranges:bytes Content-Length:18616 Cache-Control:max-age=120 Expires:Sun, 01 Jun 2008 12:37:47 GMT Content-Type:application/xml Age:2 X-Cache:HIT from 236-41.D07071951.sina.com.cn -- 反向代理伺服器使用的 HTTP 頭部 Via:1.0 236-41.D07071951.sina.com.cn:80 (squid/2.6.STABLE13) Connection:close