HTTP必知必會

作者:starok
原文地址:http://www.cnblogs.com/starstone/p/4890409.html

HTTP協(xié)議作為網(wǎng)絡(luò)傳輸?shù)幕緟f(xié)議踱蛀,有著廣泛的應(yīng)用。HTTP協(xié)議的完整內(nèi)容很多拳缠,但是其核心知識卻又簡單精煉。學(xué)習(xí)者應(yīng)該掌握其基本結(jié)構(gòu)牍白,并且能夠舉一反三脊凰。這篇文章所列的,就是在實際開發(fā)中必須知道必須掌握的HTTP知識茂腥。

HTTP協(xié)議

HTTP協(xié)議:消息的分類

HTTP消息(有的文章稱之為報文)分為請求消息和響應(yīng)消息兩種基本分類狸涌。其中請求消息是客戶端發(fā)送給服務(wù)器的用于請求服務(wù)和資源的消息,響應(yīng)消息是服務(wù)器對請求消息的應(yīng)答最岗。一般來說帕胆,一個響應(yīng)對應(yīng)一個請求,不多也不少般渡。

HTTP協(xié)議:特點

HTTP協(xié)議被人總結(jié)為無連接懒豹、無狀態(tài)的特點:

  • 無連接:無連接的含義是限制每次連接只處理一個請求。服務(wù)器處理完客戶的請求驯用,并收到客戶的應(yīng)答后脸秽,即斷開連接。采用這種方式可以節(jié)省傳輸時間蝴乔。
  • 無狀態(tài):HTTP協(xié)議是無狀態(tài)協(xié)議记餐。無狀態(tài)是指協(xié)議對于事務(wù)處理沒有記憶能力。缺少狀態(tài)意味著如果后續(xù)處理需要前面的信息薇正,則它必須重傳片酝,這樣可能導(dǎo)致每次連接傳送的數(shù)據(jù)量增大。另一方面挖腰,在服務(wù)器不需要先前信息時它的應(yīng)答就較快雕沿。

HTTP協(xié)議:消息的基本格式

HTTP協(xié)議的請求消息和響應(yīng)消息的格式及其相似。提煉出它們的共性猴仑,可以指出审轮,HTTP消息分為三個部分:

  1. 首行
  2. 頭部(Header)
  3. 正文(Body)

其中,頭部用來指出HTTP消息的一些屬性,它們有固定的格式断国;正文部分是傳輸?shù)膶嶋H內(nèi)容贤姆,它們的格式是任意的,通常用Content-Type頭來指定稳衬。首行在請求消息和響應(yīng)消息中具體格式略有區(qū)別霞捡,它們表示的按理說應(yīng)該是HTTP消息最基本的部分。不論是HTTP請求還是HTTP響應(yīng)薄疚,首行都是有的碧信,否則會出現(xiàn)不可饒恕的解析錯誤;然而頭部和正文是可選的街夭,不過實際過程中砰碴,多多少少都要包含一些基本的頭。

HTTP消息主要是基于ASCII編碼的消息實體板丽。主要的意思是指首行和頭部都是以ASCII編碼呈枉,而正文部分的編碼就顯得任意了。在實際的開發(fā)中埃碱,發(fā)送的文本消息時常會碰到亂碼的問題猖辫。一種解決辦法是,對于文本消息砚殿,約定以UTF-8格式進行編碼和解碼啃憎。

知道的人也許知道,HTTP消息是基于TCP協(xié)議的上層應(yīng)用協(xié)議辛萍。TCP協(xié)議是網(wǎng)絡(luò)流協(xié)議的一種。抽象地講羡藐,就是從一臺主機一個字節(jié)一個字節(jié)有序地傳輸?shù)搅硪慌_主機。對于HTTP協(xié)議來說仆嗦,自然保持了這種有序性,即按照首行欧啤、頭部启上、正文的順序進行傳輸。首行和頭部都是ASCII文本流冈在,正文部分是字節(jié)流倒慧。一個特殊的控制結(jié)構(gòu)CRLF用來控制每個部分的結(jié)束。

CRLF是回車符和換行符的意思,它們是兩個特殊的ASCII字符纫谅。CR是回車符(\r)炫贤,在ASCII中的編碼是13;LF是換行符(\n)付秕,在ASCII中的編碼是10.

下面通過一個例子來解釋CRLF在HTTP消息中的控制兰珍。

GET /simple.html HTTP/1.1<CRLF>     ----- 首行
Accept: text/html<CRLF>             --|
Accept-Language: zh-cn<CRLF>          |
Accept-Encoding: gzip, deflate<CRLF>  |-- 頭部
User-Agent: Mozilla/4.0<CRLF>         |
Host: localhost:8080<CRLF>            |
Connection: Keep-Alive<CRLF>        --|
<CRLF>                              ----- 空白行表示頭部的結(jié)束
                                    ----- 接下來的內(nèi)容是正文部分

這是一個簡單的HTTP請求消息。我在其中做了一些必要的刪減询吴,以便每個頭足夠短都能在一行中顯示掠河。記住首行和頭部是ASCII流,正文部分是字節(jié)流猛计,它們在消息實體中是連續(xù)的片段唠摹,并不像代碼中所示那樣有換行的結(jié)構(gòu)。換句話說奉瘤,原始的消息應(yīng)該是如下形式:

GET /simple.html HTTP/1.1<CRLF>Accept: text/html<CRLF>Accept-Language: zh-cn<CRLF>Accept-Encoding: gzip, deflate<CRLF>User-Agent: Mozilla/4.0<CRLF>Host: localhost:8080<CRLF>Connection: Keep-Alive<CRLF><CRLF>

回到之前有換行符的代碼例子中去勾拉。將每個CRLF單獨列為一行是便于觀察組織〉廖拢可以清楚地看到藕赞,第一行是首行,以CRLF標(biāo)志其結(jié)束肌访;接下來是頭部找默,含有多個消息頭,每行定義一個消息頭吼驶,以CRLF標(biāo)志其結(jié)束惩激;一個單獨的CRLF(緊接著上一個CRLF)表示整個頭部的結(jié)束,接下來是正文部分蟹演。在這個示例中风钻,正文部分為空。

另外酒请,可以看到每個消息頭的格式都是一致的骡技,即Key:Value的形式。其中Key表示消息頭的鍵羞反,Value表示消息頭的值布朦。

HTTP請求

接下來具體講講HTTP的請求消息。誠心而論昼窗,光是寫上面這么點內(nèi)容就花費了我好久是趴。每每想到寫博客耗費的精力和時間,都會影響到我寫博客的動力澄惊。

之前已經(jīng)說過富雅,HTTP請求消息也分為三個部分:

  1. 請求行
  2. 請求頭部
  3. 請求正文

其中請求頭部的格式我們已經(jīng)見過没佑。請求行的基本格式為:

方法 路徑 版本

例如下面的例子:

GET /simple.html HTTP/1.1

就有對應(yīng)關(guān)系:

  • 方法:GET
  • 路徑:/simple.html
  • 版本:HTTP/1.1

請求行是HTTP請求消息的最基本要素温赔。版本是用來聲明HTTP消息的解析規(guī)則,不同的版本在某些地方的表現(xiàn)是不同的远剩,這里不作過多拆解了『希現(xiàn)在實際應(yīng)用中最新的HTTP協(xié)議版本就是HTTP/1.1。路徑可以理解成該請求消息發(fā)往服務(wù)器的入口痢掠,一般來講嘲恍,同一個路徑應(yīng)該代表同一個資源實體。方法表示對該資源實體進行的操作淹辞,例如上述的GET方法俘侠,其含義就是請求獲取該資源的內(nèi)容。這些都是通常的解釋央星,但不是必然的要求惫东。

實際上,服務(wù)器會解析到方法和路徑颓遏,根據(jù)方法和路徑做出自己相應(yīng)的響應(yīng)滞时。這種響應(yīng)的規(guī)則,可以遵循某些規(guī)范遥皂,也可以完全不考慮這些規(guī)范刽漂,是任意的。市面上已經(jīng)存在一些約定俗成的規(guī)范了样悟,比如Restful庭猩。Restful是非常優(yōu)秀的基于HTTP協(xié)議的WEB API設(shè)計理念,很值得講震糖,但在這里就不講了趴腋。

HTTP請求:方法

首先列出最常用的HTTP方法:

  1. GET
  2. POST
  3. PUT
  4. PATCH
  5. DELETE
  6. HEAD
  7. OPTIONS

之前說過,服務(wù)器對于方法的處理颁井,是沒有強制的規(guī)范的蠢护。這句話說得并不全對。其實每個HTTP方法眉抬,都是有一些HTTP協(xié)議要求的贬芥。比如說GET方法請求的資源,瀏覽器端一般都會有緩存昏苏,下次請求的時候可能從緩存中去取就夠了威沫,服務(wù)器不用再重復(fù)發(fā)送相同的資源了;但是服務(wù)器如果將獲取資源的接口的方法定義為POST棒掠,那么瀏覽器端就不會再對資源進行緩存了,即使每次取到的都是同樣地內(nèi)容颈墅,都會請求服務(wù)器重新發(fā)送一遍。所以說恤筛,將請求資源的接口的方法定義為POST而不是GET,就是一種不合理的設(shè)計望伦。

再比如煎殷,GET方法的請求消息是不能定義消息體的,HEAD方法的請求其響應(yīng)消息是不包含消息體的劣摇,這些都是HTTP協(xié)議對于HTTP方法的約束弓乙。

HTTP請求:路徑

方法和路徑的組合構(gòu)成WEB API的入口,路徑也是很關(guān)鍵的滑潘。路徑的基本格式一般是:

basic-path[?query-string]

其中[]中的內(nèi)容表示可選的锨咙。在上例中,basic-path就是/simple.html粹舵,但不包含query-string的內(nèi)容骂倘。basic-path形式很像UNIX中絕對路徑的樣式,要以/打頭历涝。單獨的/表示一種路徑/a/a/b堰塌、/a/b/c都是合理的路徑表示分衫。不推薦使用/a/场刑、/a/b/蚪战、/a/b/c/這樣/后面不跟任何其他內(nèi)容的形式(/除外)铐懊。優(yōu)秀的API設(shè)計者會利用不同的路徑層級來合理地組織資源瞎疼。

問號后面的部分就是query-string。它的格式是任意的丑慎,只要客戶端和服務(wù)器約定好一定的形式即可瓤摧。這個部分一般是請求參數(shù)的附加。之前說過腻异,GET方法是不包含請求體的这揣,所以GET方法的HTTP請求想要附加參數(shù)只能使用這種方式。當(dāng)然其他方法也是可以使用這種方式附加參數(shù)机打,只要服務(wù)器同意就可以了片迅。query-string的格式任意,但在客戶端和服務(wù)器之間也有預(yù)先定好的約定芥挣,即鍵值對的形式耻台。query-string可以表示成一系列鍵值對的集合,用以下方式表示:

k1=v1&k2=v2&k3=&k4

在這里蹋砚,&分隔不同的鍵值對都弹,=表示鍵和值得關(guān)系匙姜。可以看到一共有四個鍵值對關(guān)系框杜,它們是:

  • k1: v1
  • k2: v2
  • k3: 空字符串
  • k4: 起碼該鍵被定義了

一般來說,鍵值對要寫成k=v的形式咪辱,但是k=和僅僅一個k都是允許的油狂,前者表示鍵k的值是空字符串,后者表示鍵k被定義了专筷,但是其值是什么并不關(guān)心磷蛹。

從上面的例子中發(fā)現(xiàn),在query-string中&=被用于特殊的用途了庇勃,我們不能再在其中從容地使用這兩個符號了槽驶。如果我們要在值中包含這兩個符號,那咋辦呢再层?方法就是堡纬,編碼烤镐。

在實際的HTTP請求中,對于如下的鍵值關(guān)系:

k1: &
k2: =

具體的query-string要寫成:

k1=%26&k2=%3D

這是因為在ASCII編碼中碗旅,&的16進制表示是26镜悉,=16進制表示是3D。對于需要的編碼旧困,就要表示成其實際編碼的16進制表示吼具,每個字節(jié)都用一個%XX三個字符進行表示。這樣拗盒,%本身也就要進行編碼了陡蝇,它的編碼是%25。除了這些控制字符的編碼登夫,還可以進行中文等非英語語言的編碼悼嫉。

對于編碼部分戏蔑,我推薦阮一峰的一篇博文:關(guān)于URL編碼

雖然看了也未必懂了鲁纠,但是最起碼知道編碼不是一件簡單的事情。

HTTP請求頭

HTTP請求頭格式與之前所說的消息頭格式?jīng)]什么兩樣情龄,就是以冒號分隔的鍵值對捍壤。HTTP請求頭中,既包含預(yù)定義的頭(如Content-Type专酗、Content-Length等)盗扇,也支持自定義頭疗隶。原本打算多列出幾個常見的請求頭的,但限于精力蒋纬,不打算這樣做了。我只說說我最常用的Content-Type頭吧法牲。

Content-Type頭琼掠,既可用于請求消息,也可用于響應(yīng)消息悼瓮,是規(guī)定請求正文內(nèi)容格式的頭部横堡。例如利用這個頭部冠桃,我們可以規(guī)定正文的格式為純文本格式食听、表單格式、XML格式葬项、JSON格式民珍、圖像格式等盗飒。例如Content-Type: application/json就表示JSON文本格式。

在小節(jié)的末尾津肛,我良心地給出一個關(guān)于HTTP預(yù)定義頭的參考網(wǎng)址:HTTP消息頭大全

HTTP響應(yīng)

HTTP響應(yīng)消息的基本格式也是一樣的汗贫,包含三個部分:

  1. 響應(yīng)行
  2. 響應(yīng)頭部
  3. 響應(yīng)正文

響應(yīng)頭部和響應(yīng)正文我覺得不需要再多說了落包。響應(yīng)行的基本格式是:

版本號 狀態(tài)碼 狀態(tài)文本

例如下面的響應(yīng)行:

HTTP/1.1 200 OK

其對應(yīng)關(guān)系為:

  • 版本號:HTTP/1.1
  • 狀態(tài)碼:200
  • 狀態(tài)文本:OK

HTTP狀態(tài)碼主要表示應(yīng)答的狀態(tài)咐蝇。狀態(tài)碼是由3個數(shù)字表示,其中第一個數(shù)字表示一個大狀態(tài),后面兩個數(shù)字表示該大狀態(tài)的一個子狀態(tài)岛请。200就表示操作成功警绩,還有其他常見的如404表示對象未找到,500表示服務(wù)器錯誤后室,403表示不能瀏覽目錄等等。

狀態(tài)碼一共分為五個大狀態(tài)岸霹,它們是:

  • 1xx
  • 2xx:請求成功處理
  • 3xx
  • 4xx:客戶端出錯
  • 5xx:服務(wù)器出錯

HTTP狀態(tài)碼大全

HTTP協(xié)議示例:

接下來的所有示例中贡避,我們將代碼都寫成前面的一行一行的模式,但略去*
*. 這時只要記住每行的結(jié)尾都暗含一個CRLF控制就可以了刮吧。例如:

GET /simple.html?bg=white HTTP/1.1
Accept: text/html
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: localhost:8080
Connection: Keep-Alive

GET請求沒有請求正文皇筛,但可以包含query-string.

POST請求可以包含請求正文,例如下面帶JSON格式正文的POST請求:

POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
Content-Type: application/json
Content-Length: 38

{"name1": "value1", "name2": "value2"}

一個返回404錯誤的響應(yīng)示例:

HTTP/1.1 404 Not Found
Date: Mon, 06 Mar 2006 09:03:14 GMT
Server: Apache/2.0.55 (Unix) PHP/5.0.5
Content-Length: 291
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
 
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /notexist was not found on this server.</p>
<hr>
<address>Apache/2.0.55 (Unix) PHP/5.0.5 Server at localhost Port 8080</address>
</body></html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蝇恶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撮弧,老刑警劉巖潘懊,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贿衍,居然都是意外死亡授舟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門贸辈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來释树,“玉大人,你說我怎么就攤上這事∩萆叮” “怎么了秸仙?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵桩盲,是天一觀的道長弊攘。 經(jīng)常有香客問我襟交,道長,這世上最難降的妖魔是什么宴合? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮该窗,結(jié)果婚禮上酗失,老公的妹妹穿的比我還像新娘褐荷。我一直安慰自己吼畏,他們只是感情好与纽,可當(dāng)我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布硬耍。 她就那樣靜靜地躺著,像睡著了一般坯认。 火紅的嫁衣襯著肌膚如雪牛哺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天,我揣著相機與錄音奴曙,去河邊找鬼。 笑死坤溃,一個胖子當(dāng)著我的面吹牛浇雹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播伐谈,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼祝旷,長吁一口氣:“原來是場噩夢啊……” “哼距贷!你這毒婦竟也來了现横?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤姜盈,失蹤者是張志新(化名)和其女友劉穎闸餐,沒想到半個月后近上,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了豺撑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡灯抛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猪半,到底是詐尸還是另有隱情磨确,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響句葵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜轻专,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一叼屠、第九天 我趴在偏房一處隱蔽的房頂上張望嫂侍。 院中可真熱鬧菲盾,春花似錦懒鉴、人聲如沸璃俗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至叹话,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間热凹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工突诬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留骏令,地道東北人。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓高蜂,卻偏偏與公主長得像备恤,于是被迫代替她去往敵國和親喉镰。 傳聞我的和親對象是個殘疾皇子惭笑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 引言 HTTP是一個屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議,由于其簡捷捺宗、快速的方式川蒙,適用于分布式超媒體信息系統(tǒng)。它于1990年...
    _燴面_閱讀 1,328評論 0 9
  • HTTP是一個屬于應(yīng)用層的面向?qū)ο蟮膮f(xié)議畜眨,由于其簡捷、快速的方式恬汁,適用于分布式超媒體信息系統(tǒng)。它于1990年提出游昼,...
    lilinjianshu閱讀 520評論 0 1
  • 1、常用的HTTP方法有哪些靖榕? GET:用于請求訪問已經(jīng)被URI(統(tǒng)一資源標(biāo)識符)識別的資源星压,可以通過URL傳參給...
    passiontim閱讀 2,078評論 0 11
  • 一個人需要隱藏多少秘密 才能巧妙地度過一生 這佛光閃閃的高原 三步兩步便是天堂 卻仍有那么多人 因心事過重而走不動...
    淑琦記閱讀 283評論 0 1
  • 忽睹天際彩云锄贼,常疑好事皆虛事票灰;再觀山中古木,方信閑人是福人。 迷則樂境成苦海屑迂,如水凝為冰浸策;悟則苦海為樂境,猶冰渙作...
    HedyWang1閱讀 123評論 0 0