前端接入HTTP协议浅析
【摘要】:本文整理并簡要分析了HTTP協議的交互過程和內容格式,包括HTTP請求、HTTP應答的頭域和實體內容,HTTP 1.0與HTTP 1.1的差異,并舉例說明了Chunked編碼的工作過程原理。
?
1、HTTP協議簡介
? ?瀏覽器和Web服務器之間一問一答的交互過程遵守一定的規則,這個規則就是HTTP協議。HTTP協議時TCP/IP協議集中的一個應用層協議,定義了瀏覽器和Web服務器之間交換數據過程和數據本身的格式。現在廣泛應用的有HTTP/1.0和HTTP/1.1兩個版本,1.1和1.0相比最大的特點就是增加對長連接的支持。
2、協議流程
2.1 HTTP/1.0的通信過程
?????? HTTP/1.0只支持短連接,每次連接只處理一個請求,即使對同一站點的每一個頁面的訪問,瀏覽器和服務器之間都要建立一次單獨的鏈接。通信過程如圖1所示:
2.2 HTTP /1.1的通信過程
? HTTP/1.1支持長連接,在一個TCP連接上可以傳送多個HTTP請求和應答,減少建立和關閉連接的消耗和延遲。例如一個包含多張圖片資源的網頁文件的多個請求和響應可以在同一個連接中傳輸,并且還允許瀏覽器客戶端不用等待上一次請求的結果返回就可以發送下一個請求,也就是支持pipeline管線化。HTTP 1.1的通信過程如圖2所示:
3、HTTP請求
? ?完整的HTTP請求包括:一個請求行、若干HTTP頭域和可選的實體內容三部分:
3.1 請求行
??請求行以一個方法符號開頭,以空格分開,后面跟著請求的URI和協議版本,格式如下:
?????? Method? Request-URI? HTTP-Version CRLF
????? 其中的Method表示請求方法,Request-URI是同一資源標識符,HTTP-Version表示請求的HTTP協議版本,CRLF表示回車換行。
????? 請求方法有8種,方法名全為大寫:
????? (1)GET??? 請求獲取Request-URI指定的資源
????? (2)HEAD 請求獲取Request-URI制定資源的響應消息報頭
????? (3)POST? 用于向服務器提交數據,正常情況下帶有“消息體”
????? (4)PUT??? 請求服務器存儲一個資源,并用Request-URI作為其標識
?????? (5)DELETE????? 請求服務器刪除Request-URI所標識的資源
(6)TRACE?? 請求服務器回送收到的請求信息,主要用于測試或診斷
(7)CONNECT保留將來使用
(8)OPTIONS請求查詢服務器的性能,或者查詢與資源相關的選項和需求
3.2?? HTTP頭域
????? HTTP頭域分為四種:通用頭域、請求頭域、響應頭域和實體頭域。每個頭域由一個域名、冒號和域值三部分組成,域名大小寫無關,域值前可以添加任何數量的空格符。
3.2.1? 通用頭域
????? 通用頭域是指請求和響應都支持的HTTP頭域,最常見的有Cache-Control、Connection和Transfer-Encoding,具體含義如下:
(1)??? Cache-Control:指定請求和相應遵循的緩存機制,最常見的值是no-cache,指示請求和響應消息不能緩存;
(2)??? Connection:用于指定處理完本次請求/響應后,客戶端和服務器是否還要繼續保持連接。
(3)??? Transfer-Encoding:用于指定實體內容的傳輸編碼方式。
3.2.2? 請求頭域
????? 請求頭域是只有在請求頭中帶有的,用于向服務器傳遞關于請求或者關于客戶端的附件信息。常見的有:Accept、Accept-Encoding、Accept-Language、Accept-Charset、Host、Referer、User-Agent和Cookie,具體含義如下:
(1)??? Accept:用于指定客戶端程序能夠處理的MIME類型,多個時用逗號隔開;
(2)??? Accept-Encoding:指定客戶端程序支持的壓縮方式;
(3)??? Accept-Language:指定客戶端期望返回哪個國家語言的文檔;
(4)??? Accept-Charset:指定客戶端程序可以使用的字符集;
(5)??? Host:指定資源所在的主機名和端口號;
(6)??? Referer:指定請求uri的源資源地址,也就是用戶從哪個uri過來,允許服務器生成回退鏈表;
(7)??? User-Agent:瀏覽器客戶端信息,如使用哪種瀏覽器等;
(8)??? Cookie:服務器在瀏覽器端留下的信息,這是最重要的請求頭字段之一,例如訪問百度的時候通常會帶有類似如下的Cookie:
BAIDUID=27C48D40C9CDCF48CEAAFCFD9C47FC52:FG=1;BD_UTK_DVT=1
3.2.3? 響應頭域
????? 響應頭域只在HTTP響應中出現,在第4章節詳細講解。
3.2.4? 實體頭域
????? HTTP請求和響應中都可以包含實體頭域,實體頭域包含實體內容的一些信息。常見的實體頭域有:Content-Encoding、Content-Length、Content-Type和Expires,具體含義如下:
(1)??? Content-Encoding:指明實體內容采用的壓縮方式;
(2)??? Content-Length:指明實體內容的長度,單位為字節;
(3)??? Content-Type:指定實體內容的MIME類型;
(4)??? Expires:指明實體內容在什么時間之后過期,不再緩存。
3.2?? 可選實體內容
????? HTTP請求是否帶有實體內容主要看請求行中的請求方法,我們只分析GET和POST兩種主要的類型,GET方法用于獲取服務器上的特定資源,一般沒有實體內容。POST方法用于向服務器提交數據,一般帶有實體內容。下面是一個請求方法為POST的HTTP請求的完整數據(其中綠色標注的部分是實體內容):
POST /deal_post.phpHTTP/1.1
Referer: http://db-testing-ps1101.db01.baidu.com:8080/post.php
Accept-Language: zh-cn
Content-Type:application/x-www-form-urlencoded
User-Agent: Mozilla/4.0
Host:db-testing-ps1101.db01.baidu.com:8080
Content-Length: 43
Connection: Keep-Alive
Cache-Control: no-cache
Cookie:BAIDUID=27C48D40C9CDCF48CEAAFCFD9C47FC52:FG=1;
?
data1=a&data2=b&data3=c&Submit=%CC%E1%BD%BB
4、HTTP應答
HTTP應答包括:一個狀態行、若干消息頭和實體內容三部分組成。
4.1 狀態行
狀態行以HTTP協議版本開頭,后面跟著狀態碼和簡單的狀態描述,格式如下:
?????? HTTP-Version ?Status-Code? Reason-Phrase? CRLF
?????? 其中的Status-Code是一個三個數字組成的返回狀態碼,Reason-Phrase提供一個簡單的狀態描述,如對于200成功頁面就是“OK”,對于404頁面未找到錯誤就是“Not Found”。
????? HTTP應答的狀態行根據狀態碼可以分為五種類型:
(1)1xx:信息,請求收到,繼續處理;
(2)2xx:成功,行為被成功地接受、理解和采納;
(3)3xx:重定向,為了完成請求,必須進一步執行的動作;
(4)4xx:客戶端錯誤,請求包含語法錯誤或者請求無法實現;
(5)5xx:服務端錯誤,服務器不能正確執行一個正確的請求。
下表中是檢索前段Web服務器測試中常見的幾種返回狀態碼:
4.2 HTTP頭域
??前面我們介紹過HTTP頭域可以分為四種,HTTP應答包含通用頭域、響應頭域和實體頭域,通用頭域和實體頭域前面已經介紹過,本節主要介紹響應頭域。
? ?響應頭域允許服務器傳遞不能放在狀態行中的附件信息,主要用于描述服務器的信息和Request URI的進一步信息,檢索前段Web服務器測試中最常見的響應頭域有Server、Location、Set-Cookie和P3P,具體含義如下:
(1)?????? Server:說明響應服務器的名稱,如BWS/1.0或者Apache/1.3.27;
(2)?????? Location:在302跳轉頁面應答的時候,帶有Location指明跳轉的目的地址;
(3)?????? Set-Cookie:服務器對瀏覽器端設置Cookie,例如不帶Cookie訪問BWS的時候,BWS會返回類似如下的Set-Cookie內容:
BAIDUID=B589E67D8A2C6B15C2FDD8F20C3DC0D5:FG=1;expires=Wed, 26-Aug-39 01:47:59 GMT; path=/; domain=.baidu.com
(4)?????? P3P:設置允許Cookie的跨域訪問,BWS模塊在設置Cookie的時候通常會帶有該頭域
P3P: CP=" OTI DSP COR IVA OUR IND COM"
4.3 實體內容
? HTTP響應的實體內容按照傳輸編碼方式(編碼的目的是讓瀏覽器和服務器之間能正確收發數據)區分主要分為三種:
(1)?????? 由Content-Length明確標明實體內容,這是最常見的一種類型;
(2)?????? 沒有Content-Length頭域,由Transfer-Encoding指明采用Chunked編碼;
(3)?????? 既沒有Content-Length也沒有Transfer-Encoding標明采用Chunked編碼;
4.3.1? Content-Length類型
??這是最常見的一種類型,由Content-Length頭域標明后續的實體內容的字節長度,瀏覽器或者服務器根據解析出來的Content-Length去讀取后續的實體內容。下面是一個該類型的HTTP響應(綠色部分是實體內容,長度為20個字節):
HTTP/1.1 200 OK
Date: Wed, 26 Aug 2009 02:45:57 GMT
Server: Apache/2.0.63 (Unix) PHP/5.2.6
Content-Length: 20
Content-Type: text/html
Content-Language: en
?
<html>content</html>
4.3.2? Chunked類型
? ?Chunked編碼類型也是較常見的,當服務器不能預先確定HTTP報文體的長度時,無法在應答頭域Content-Length域來指明報文體長度,此時需要采用chunked編碼,通過Transfer-Encodeing頭域說明采用chuncked編碼。檢索前段模塊中Apache-snap很多地方就采用了Chunked編碼,而BWS不支持Chunked編碼。
chunked編碼的基本方法是將大塊數據分解成多塊小數據,每塊都可以自指定長度,其具體格式如下:
Chunked-Body??= *chunk??????? //0至多個chunk
??????????????????????????? last-chunk???? //最后一個chunk
?????????????????????????? trailer??????????? ?//尾部
???????????????????????? CRL?????????????? //結束標記符
??chunk????????? ? = chunk-size [ chunk-extension ]CRLF??
???????????????????????? ? chunk-data CRLF
??chunk-size????= 1*HEX
??last-chunk????= 1*("0") [ chunk-extension ] CRLF
??chunk-extension=*( ";" chunk-ext-name [ "=" chunk-ext-val ] )
??chunk-ext-name= token
??chunk-ext-val?= token | quoted-string
??chunk-data????= chunk-size(OCTET)
??trailer???????= *(entity-header CRLF)?? ?
?
Chunked-Body表示經過chunked編碼后的報文體。報文體可以分為chunk, last-chunk,trailer和結束符四部分。chunk的數量在報文體中最少可以為0,無上限;每個chunk的長度是自指定的,即起始的數據必然是16進制數字的字符串,代表后面chunk-data的長度(字節數)。這個16進制的字符串第一個字符如果是“0”,則表示chunk-size為0,該chunk為last-chunk,無chunk-data部分。可選的chunk-extension由通信雙方自行確定,如果接收者不理解它的意義,可以忽略。
trailer是附加的在尾部的額外頭域,通常包含一些元數據(metadata, meta means"about information"),這些頭域可以在解碼后附加在現有頭域之后。
??下面我們以一個實例來分析一下chunked編碼頁面,首先在apache(本機端口9000)的發布目錄htdocs下準備一個文件test.php,內容如下:
<html>
<head>
<title>Hi</title>
<linkrel="stylesheet" href="style.css" type="text/css"
media="all"/>
</head>
<?phpflush(); sleep(5); ?>
<bodyοnlοad="loaded();">
<h1>Hi</h1>
</body>
</html>
在測試機上通過echo –ne ?“GET /test.phpHTTP/1.1\r\nHost: www.baidu.com\r\n\r\n” | nc 127.0.0.1 9000訪問該頁得到的結果如下:
查看應答的二進制內容如下:
由應答報文可以看出,在頭域結束符“\r\n\r\n”之后是ASCII碼74,表示第一個chunk的chunk-size,轉換為十進制是116字節,74后面緊接著“\r\n”是chunk-size和chunk-data的分隔符,因此這里沒有chunk-extension,這里我們可以看出頭域結束符“\r\n\r\n”之后緊接的地址是000000E7,在000000E7后面是37 34 0d 0a,也就是“74\r\n”,74表示第一個chunk-data的十六進制長度,那么第一個chunk-data的起始地址就是000000EB,下一個chunk的起始地址就是000000EB + 74 + 2 = 00000161,在0000015F的位置我們可以看到0d 0a 32 39 0d 0a,也就是“\r\n29\r\n”,前一個“\r\n”表示上一個chunk的結束,然后29表示十六進制的下一個chunk-data的長度,后一個“\r\n”是chunk-size和chunk-data的分隔符。
從0000015F+ 2 + 2 + 2 = 00000165開始為第二個chunk-data的數據,長度為41個字節,于是下一個chunk的起始位置就是00000165 + 29 = 0000018E,這個地方的數據是0d 0a 30 0d 0a,也就是“0\r\n\r\n”,0作為chunk-size表示這個chunk為最后一個chunk,第一個“\r\n”表示最后一個chunk的結束,而第二個“\r\n”表示沒有tailer部分,整個chunk-body結束。
4.3.3? 特殊類型
??特殊類型指的是HTTP響應中既沒有Content-Length指明實體內容的長度,也沒有Transfer-Encoding指明采用Chunked編碼,只是服務器在發送完響應之后就直接關閉連接。
??下面是一個特殊類型HTTP應答的例子:
HTTP/1.1413?Request?Entity?Too?Large Date:Wed,?26?Aug?2009?05:16:39?GMT Server:Apache/2.0.63?(Unix)?PHP/5.2.6 Vary:Accept-Encoding Connection:close Content-Type:text/html;?charset=iso-8859-1<!DOCTYPEHTML?PUBLIC?"-//IETF//DTD?HTML?2.0//EN"> <html><head> <title>413Request?Entity?Too?Large</title> </head><body> ……5、參考鏈接
(1)?????? http://tools.ietf.org/html/rfc2616
?
? ?百度MTC是業界領先的移動應用測試服務平臺,為廣大開發者在移動應用測試中面臨的成本、技術和效率問題提供解決方案。同時分享行業領先的百度技術,作者來自百度員工和業界領袖等。
>>如有問題,歡迎與我溝通
轉載于:https://blog.51cto.com/11009914/1734249
總結
以上是生活随笔為你收集整理的前端接入HTTP协议浅析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nmap入门之主机发现
- 下一篇: 2017年html5行业报告,云适配发布