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