HTTP請(qǐng)求報(bào)文
HTTP的報(bào)文大概分三大部分筏养。第一部分是請(qǐng)求行藏澳,第二部分是請(qǐng)求的首部,第三部分才是請(qǐng)求的正文實(shí)體锣杂。
-
請(qǐng)求行
- 基本語(yǔ)法:Method 空格 Request-URI 空格 HTTP版本 換行脂倦。比如:POST /bauhinia/v1/class/purchase/info HTTP/1.1。
- 方法(常用方法)
- GET GET 就是去服務(wù)器獲取一些資料
- POST 它需要主動(dòng)告訴服務(wù)端一些信息元莫,而非獲取赖阻。POST 往往是用來(lái)創(chuàng)建一個(gè)資源的。
- PUT 它是指定資源位置上傳最新內(nèi)容踱蠢。PUT 往往是用來(lái)修改一個(gè)資源的火欧。
- DELETE 它是用來(lái)刪除資源。
-
請(qǐng)求頭(request header)
- 首部字段 茎截。首部是 key value布隔,通過(guò)冒號(hào)分隔。這里面稼虎,往往保存了一些非常重要的字段衅檀。
- Accept-Charset,表示客戶(hù)端可以接受的字符集。防止傳過(guò)來(lái)的是另外的字符集霎俩,從而導(dǎo)致出現(xiàn)亂碼哀军。
- Content-Type,表示正文的格式,例如我們進(jìn)行POST 的請(qǐng)求打却,如果正文是JSON 那么我們就應(yīng)該將這個(gè)值設(shè)置為JSON杉适。
- Content-Length ,表示請(qǐng)求體的長(zhǎng)度;
- Cache-control,用來(lái)控制緩存的柳击。當(dāng)客戶(hù)端發(fā)送的請(qǐng)求中包含 max-age 指令時(shí)猿推,如果判定緩存層中,資源的緩存時(shí)間數(shù)值比指定時(shí)間的數(shù)值小捌肴,那么客戶(hù)端可以接受緩存的資源蹬叭;當(dāng)指定 max-age 值為 0,那么緩存層通常需要將請(qǐng)求轉(zhuǎn)發(fā)給應(yīng)用集群状知。
- If-Modified-Since 也是一個(gè)關(guān)于緩存的秽五。也就是說(shuō),如果服務(wù)器的資源在某個(gè)時(shí)間之后更新了饥悴,那么客戶(hù)端就應(yīng)該下載最新的資源坦喘;如果沒(méi)有更新,服務(wù)端會(huì)返回“304 Not Modified”的響應(yīng)西设,那客戶(hù)端就不用下載了瓣铣,也會(huì)節(jié)省帶寬。
- 首部字段 茎截。首部是 key value布隔,通過(guò)冒號(hào)分隔。這里面稼虎,往往保存了一些非常重要的字段衅檀。
- 請(qǐng)求體(body)
- POST 方法會(huì)攜帶請(qǐng)求體贷揽,通過(guò) key=value 的形式把不同的值使用&拼接起來(lái)棠笑。
HTTP 請(qǐng)求發(fā)送
從上圖我們看出一個(gè)請(qǐng)求從我們電腦里發(fā)出請(qǐng)求包括的內(nèi)容:MAC 頭 IP 頭 TCP 頭 HTTP。
HTTP 協(xié)議是基于TCP 協(xié)議的擒滑,所以它使用的面向連接的方式發(fā)送請(qǐng)求腐晾,通過(guò) stream 二進(jìn)制流的方式傳給對(duì)方。 到了TCP 層 它會(huì)把二進(jìn)制流變成一個(gè)的報(bào)文段發(fā)送給服務(wù)器丐一。
在發(fā)送給每個(gè)報(bào)文段的時(shí)候藻糖,都需要對(duì)方回應(yīng)一個(gè)ACK,來(lái)保證報(bào)文可靠的到達(dá)了對(duì)方库车。如果沒(méi)有回應(yīng)巨柒,那么TCP 這一層會(huì)進(jìn)行重新傳輸,直到可以到達(dá)柠衍。同一個(gè)包有可能被傳了多次洋满,但HTTP 這一層不需要知道這一點(diǎn),因?yàn)槭荰CP 在這一層埋頭苦干珍坊。
TCP 層發(fā)送一個(gè)報(bào)文的時(shí)候牺勾,都需要加上自己的地址(即源地址)和它想要去的地方(即目標(biāo)地址),將這兩個(gè)信息放到IP頭里面阵漏,交給 iP 層進(jìn)行傳輸驻民。
IP 層需要查看目標(biāo)地址和自己是否是在一個(gè)局域網(wǎng)。如果是履怯,就發(fā)送ARP 協(xié)議來(lái)請(qǐng)求這個(gè)目標(biāo)地址對(duì)應(yīng)的MAC 地址回还, 然后將這個(gè)源 MAC 和網(wǎng)關(guān) MAC 放入 MAC 頭 發(fā)送出去。
網(wǎng)關(guān)收到包發(fā)現(xiàn)MAC 符合叹洲,取出目標(biāo)IP 地址柠硕,根據(jù)路由協(xié)議找到下一跳的路由器,獲取下一跳路由器的 MAC 地址运提, 將包發(fā)給下一跳路由器蝗柔。
這樣路由器一跳一跳終于到達(dá)目標(biāo)的局域網(wǎng)。 這個(gè)時(shí)候 最后一跳的路由器發(fā)現(xiàn)目標(biāo)地址就在自己的某一個(gè)出口的局域網(wǎng)上民泵。于是就在這個(gè)局域網(wǎng)上發(fā)送ARP 獲得這個(gè)目標(biāo)地址的MAC 地址诫咱,將包發(fā)送出去。
目標(biāo)地址大學(xué)MAC 地址符合洪灯,就將包收起來(lái)坎缭; 發(fā)現(xiàn) IP 地址 符合,根據(jù) IP 頭中的協(xié)議項(xiàng)签钩,知道自己上一層是TCP 協(xié)議掏呼,于是解析 TCP 的頭,里面有序列號(hào)铅檩,需要看一看這個(gè)序列包是不是我要的憎夷,如果是就放入緩存中然后返回一個(gè)ACK,如果不是就丟棄昧旨。
TCP 頭里面還有端口號(hào)拾给,HTTP 的服務(wù)器正在監(jiān)聽(tīng)這個(gè)端口號(hào)祥得。于是,目標(biāo)機(jī)器自然知道是HTTP 服務(wù)器這個(gè)進(jìn)程想要這個(gè)包蒋得,于是將包發(fā)給HTTP 服務(wù)器级及。HTTP 服務(wù)器的進(jìn)程看到 原來(lái)這個(gè)請(qǐng)求是要訪問(wèn)一個(gè)網(wǎng)頁(yè),于是就把這個(gè)網(wǎng)頁(yè)發(fā)給客戶(hù)端。
HTTP 返回報(bào)文
HTTP 返回頭格式和請(qǐng)求頭大致一樣包括 狀態(tài)行额衙、請(qǐng)求頭饮焦、請(qǐng)求體。
-
狀態(tài)行(status line)
- 基本語(yǔ)法:HTTP版本 空格 狀態(tài)碼 空格 原因短語(yǔ)窍侧。
- 狀態(tài)碼(有 5 大類(lèi)狀態(tài)碼)
- 1XX :Informational - Request received, continuing process县踢,表示服務(wù)端已經(jīng)接收到請(qǐng)求正在處理中;
- 2XX :Success - The action was successfully received, understood, and accepted伟件,表示服務(wù)端明白了客戶(hù)端要干什么硼啤,也可以做出正確的響應(yīng);
- 3XX: Redirection - Further action must be taken in order to complete the request斧账,重定向丙曙,我處理不了你的請(qǐng)求,我需要把它交給其它小伙伴處理其骄;
- 4XX :Client Error - The request contains bad syntax or cannot be fulfilled亏镰,客戶(hù)端錯(cuò)誤,服務(wù)端理解不了請(qǐng)求對(duì)象拯爽,要么是地址寫(xiě)錯(cuò)了索抓,要么是不符合規(guī)則;
- 5XX :Server Error - The server failed to fulfill an apparently valid request毯炮,服務(wù)端錯(cuò)誤逼肯,這個(gè)時(shí)候你可以找服務(wù)端小伙伴說(shuō):“你的服務(wù)掛了”。
-
響應(yīng)頭(response header)
- 這部分和請(qǐng)求頭一樣 桃煎。首部是 key value篮幢,通過(guò)冒號(hào)分隔。
- Retry-After ,告訴客戶(hù)端應(yīng)該在多長(zhǎng)時(shí)間以后再次嘗試一下为迈∪唬“503 錯(cuò)誤”是說(shuō)“服務(wù)暫時(shí)不再和這個(gè)值配合使用”。
- 這部分和請(qǐng)求頭一樣 桃煎。首部是 key value篮幢,通過(guò)冒號(hào)分隔。
-
響應(yīng)體(body)
- 主要通過(guò)這些數(shù)據(jù)來(lái)做一些業(yè)務(wù)處理葫辐。
HTTP 2.0
隨著HTTP 協(xié)議不斷的搜锰,在HTTP1.1基礎(chǔ)上便有了HTTP 2.0。
HTTP 1.1 在應(yīng)用層以純文本的形式進(jìn)行通信耿战。每次通信都要帶完整的 HTTP 的頭蛋叼,而且不考慮 pipeline(管線化)模式的話,每次過(guò)程總是像上面描述的那樣一來(lái)一回 在實(shí)時(shí)性、并發(fā)性都存在問(wèn)題狈涮。
為了解決這些問(wèn)題狐胎,HTTP 2.0 會(huì)對(duì) HTTP 的頭進(jìn)行一定的壓縮,將原來(lái)每次都要攜帶的大量 key value 在兩端建立一個(gè)索引表歌馍,對(duì)相同的頭只發(fā)送索引表中的索引握巢。
另外,HTTP 2.0 協(xié)議將一個(gè) TCP 的連接中骆姐,切分成多個(gè)流,每個(gè)流都有自己的 ID捏题,而且流可以是客戶(hù)端發(fā)往服務(wù)端玻褪,也可以是服務(wù)端發(fā)往客戶(hù)端。它其實(shí)只是一個(gè)虛擬的通道公荧。流是有優(yōu)先級(jí)的带射。
HTTP 2.0 還將所有的傳輸信息分割為更小的消息和幀,并對(duì)它們采用二進(jìn)制格式編碼循狰。常見(jiàn)的幀有 Header 幀窟社,用于傳輸 Header 內(nèi)容,并且會(huì)開(kāi)啟一個(gè)新的流绪钥。再就是 Data 幀灿里,用來(lái)傳輸正文實(shí)體。多個(gè) Data 幀屬于同一個(gè)流程腹。
通過(guò)這兩種機(jī)制匣吊,HTTP 2.0 的客戶(hù)端可以將多個(gè)請(qǐng)求分到不同的流中,然后將請(qǐng)求內(nèi)容拆成幀寸潦,進(jìn)行二進(jìn)制傳輸色鸳。這些幀可以打散亂序發(fā)送, 然后根據(jù)每個(gè)幀首部的流標(biāo)識(shí)符重新組裝见转,并且可以根據(jù)優(yōu)先級(jí)命雀,決定優(yōu)先處理哪個(gè)流的數(shù)據(jù)。
HTTP 1.1 是串行的斩箫。 HTTP 2.0 是并行的吏砂。
來(lái)自趣談網(wǎng)絡(luò)協(xié)議 https://time.geekbang.org/column/intro/85