前段時(shí)間看了《御賜小仵作》,里面有很多細(xì)節(jié)很有心。看了一些評(píng)論都是:終于在劇里能夠看到真正在搞事業(yè)、發(fā)了工資第一時(shí)間還錢(qián)的正常人了。我印象比較深的是王府才能吃上的葡萄。覺(jué)得非常合理。劇里說(shuō)的明明白白,是唐朝中晚期唐宣宗的時(shí)候,那時(shí)候絲綢之路剛剛開(kāi)通,西域(現(xiàn)在的新疆以及更西的地方)的葡萄終于能吃上了,這就和那一整段歷史給對(duì)應(yīng)上了。
談到對(duì)應(yīng)的問(wèn)題,咱們回到正題,http狀態(tài)碼1XX。對(duì)于http狀態(tài)200、404、500,大家可能熟悉一些。1XX可能實(shí)際中從來(lái)沒(méi)有見(jiàn)過(guò),今天咱們用剝洋蔥的敘述方式,撥開(kāi)1XX狀態(tài)碼的層層面紗。
定義
HTTP狀態(tài)碼(英語(yǔ):HTTP Status Code)是用以表示網(wǎng)頁(yè)服務(wù)器超文本傳輸協(xié)議響應(yīng)狀態(tài)的3位數(shù)字代碼。這句話(huà)要注意解讀了。我先來(lái)考考大家讀懂了沒(méi)。請(qǐng)回答:
這里我先不回答,無(wú)法決定的朋友再多讀幾遍定義。
狀態(tài)碼1XX表示服務(wù)端已經(jīng)收到了請(qǐng)求,但是還需要進(jìn)一步處理。
白居易有一首《問(wèn)劉十九》:
綠蟻新醅酒,紅泥小火爐。
晚來(lái)天欲雪,能飲一杯無(wú)?
這就和服務(wù)端可能會(huì)返回1XX的場(chǎng)景很像??蛻?hù)端發(fā)起一個(gè)請(qǐng)求:我這里有美酒和暖爐,天要下雪了,來(lái)喝一杯?服務(wù)端收到之后返回1XX。代表接受邀請(qǐng)。這時(shí)候客戶(hù)端就可以真正擺上一桌酒菜迎接客人了。如果服務(wù)端返回4XX,客戶(hù)端也不用消耗資源殺雞做菜了。
1xx狀態(tài)碼是 HTTP/1.1 版本新定義的,用來(lái)表示請(qǐng)求被正常接收,會(huì)進(jìn)行進(jìn)一步處理。這些狀態(tài)碼相對(duì)較新,并且 HTTP/1.0 版本無(wú)法識(shí)別,所以原則上不應(yīng)該向HTTP/1.0版本的客戶(hù)端發(fā)送任何1xx狀態(tài)碼。
100 Continue
該狀態(tài)碼說(shuō)明服務(wù)器收到了請(qǐng)求的初始部分,并請(qǐng)客戶(hù)端繼續(xù)發(fā)送。在服務(wù)器發(fā)送了 100 Continue 狀態(tài)碼之后,如果收到客戶(hù)端的請(qǐng)求,則必須進(jìn)行響應(yīng)。
這個(gè)狀態(tài)碼實(shí)際上是對(duì)如下場(chǎng)景的一種優(yōu)化:客戶(hù)端有一個(gè)較大的文件需要上傳并保存,但是客戶(hù)端不知道服務(wù)器是否愿意接受這個(gè)文件,所以希望在消耗網(wǎng)絡(luò)資源進(jìn)行傳輸之前,先詢(xún)問(wèn)一下服務(wù)器的意愿。實(shí)際操作為客戶(hù)端發(fā)送一條特殊的請(qǐng)求報(bào)文,報(bào)文的頭部應(yīng)包含
Expect: 100-continue
此時(shí),如果服務(wù)器愿意接受,就會(huì)返回 100 Continue 狀態(tài)碼,反之則返回 417 Expectation Failed 狀態(tài)碼。對(duì)于客戶(hù)端而言,如果客戶(hù)端沒(méi)有發(fā)送實(shí)際請(qǐng)求的打算,則不應(yīng)該發(fā)送包含 100 Continue Expect 的報(bào)文,因?yàn)檫@樣會(huì)讓服務(wù)器誤以為客戶(hù)端將要發(fā)送一個(gè)請(qǐng)求。大家可以基于對(duì)100的理解再回想一下《問(wèn)劉十九》。
之前提到過(guò),并不是所有的HTTP應(yīng)用都支持 100 Continue 這個(gè)狀態(tài)碼(例如HTTP/1.0及之前的版本的代理或服務(wù)器)所以客戶(hù)端不應(yīng)該在發(fā)送 100 Continue Expect 后一直等待服務(wù)器的響應(yīng),在一定時(shí)間后,客戶(hù)端應(yīng)當(dāng)直接發(fā)送計(jì)劃發(fā)送的內(nèi)容。
而對(duì)于服務(wù)器而言,也不應(yīng)當(dāng)把 100 Continue 當(dāng)作一個(gè)嚴(yán)格的判斷方法。服務(wù)器有可能在發(fā)送回應(yīng)之前就收到了客戶(hù)端發(fā)來(lái)的主體報(bào)文。此時(shí)服務(wù)器就不需要再發(fā)送 100 Continue 作為回應(yīng)了。但仍然需要在接受完成后返回適當(dāng)?shù)臓顟B(tài)碼。理論上,當(dāng)服務(wù)器收到一個(gè) 100 Continue Expect 請(qǐng)求時(shí),應(yīng)當(dāng)進(jìn)行響應(yīng)。但服務(wù)器永遠(yuǎn)也不應(yīng)向沒(méi)有發(fā)送 100 Continue Expect 請(qǐng)求的客戶(hù)端發(fā)送100 Continue 狀態(tài)碼作為回應(yīng)。這里提到的應(yīng)當(dāng)進(jìn)行響應(yīng)是指:假設(shè)服務(wù)器不打算接收客戶(hù)端將要發(fā)送的主體報(bào)文,也應(yīng)當(dāng)做適當(dāng)?shù)捻憫?yīng)(例如發(fā)送 417 Expectation Failed)而不是單純的關(guān)閉連接,這樣會(huì)對(duì)客戶(hù)端在網(wǎng)絡(luò)層面上產(chǎn)生影響。
作為代理的HTTP應(yīng)用在收到帶有 100 Continue Expect 的請(qǐng)求時(shí),需要進(jìn)行額外的判斷。假設(shè)代理服務(wù)器明確知道報(bào)文下游的HTTP版本是兼容 HTTP/1.1 的,或者代理服務(wù)器不知道報(bào)文下游的版本,它都應(yīng)當(dāng)轉(zhuǎn)發(fā)這條 100 Continue Expect 請(qǐng)求。但是如果代理服務(wù)器明確知道報(bào)文下游的應(yīng)用無(wú)法處理 100 Continue Expect 的話(huà),則應(yīng)當(dāng)直接向客戶(hù)端返回 417 Expectation Failed 作為響應(yīng)。而這也并非唯一的解決辦法,另一種可行的辦法是直接向客戶(hù)端返回 100 Continue ,然后向下游傳遞刪除了 100 Continue Expect 的報(bào)文。
另外,如果代理服務(wù)器決定為 HTTP/1.0 及之前的版本服務(wù)的話(huà),那么當(dāng)它收到來(lái)自服務(wù)器的 100 Continue 響應(yīng)報(bào)文時(shí),則不應(yīng)當(dāng)向客戶(hù)端轉(zhuǎn)發(fā)這條響應(yīng),因?yàn)榭蛻?hù)端很可能不知道如何處理該報(bào)文。
101 Switching Protocols
HTTP 101 Switching Protocol(協(xié)議切換)狀態(tài)碼表示服務(wù)器應(yīng)客戶(hù)端升級(jí)協(xié)議的請(qǐng)求對(duì)協(xié)議進(jìn)行切換。
此機(jī)制始終由客戶(hù)端發(fā)起,并且服務(wù)器可能接受或拒絕切換到新協(xié)議??蛻?hù)端可使用常用的協(xié)議(如HTTP / 1.1)發(fā)起請(qǐng)求,請(qǐng)求說(shuō)明需要切換到HTTP / 2或甚至到WebSocket。
我們來(lái)看一個(gè)實(shí)際的例子:
為了實(shí)現(xiàn)WebSocket通信,首先需要客戶(hù)端發(fā)起一次普通HTTP請(qǐng)求。也就是說(shuō),WebSocket的建立是依賴(lài)HTTP的。
其中HTTP頭部字段Upgrade: websocket和Connection: Upgrade非常重要,告訴服務(wù)器通信協(xié)議將發(fā)生改變,轉(zhuǎn)為WebSocket協(xié)議。支持WebSocket的服務(wù)器端在確認(rèn)以上請(qǐng)求后,應(yīng)返回狀態(tài)碼為101 Switching Protocols的響應(yīng):
其中字段Sec-WebSocket-Accept是由服務(wù)器對(duì)前面客戶(hù)端發(fā)送的Sec-WebSocket-Key進(jìn)行確認(rèn)和加密后的結(jié)果,相當(dāng)于一次驗(yàn)證,以幫助客戶(hù)端確信對(duì)方是真實(shí)可用的WebSocket服務(wù)器。
驗(yàn)證通過(guò)后,這個(gè)握手響應(yīng)就確立了WebSocket連接,此后,服務(wù)器端就可以主動(dòng)發(fā)信息給客戶(hù)端了。此時(shí)的狀態(tài)比較像服務(wù)器端和客戶(hù)端接通了電話(huà),無(wú)論是誰(shuí)有什么信息想告訴對(duì)方,開(kāi)口就好了。
一旦建立了WebSocket連接,此后的通信就不再使用HTTP了,改為使用WebSocket獨(dú)立的數(shù)據(jù)幀。
102 Processing
Web服務(wù)器可能需要相當(dāng)長(zhǎng)的時(shí)間來(lái)處理復(fù)雜的請(qǐng)求。當(dāng)客戶(hù)端的瀏覽器發(fā)送包含多個(gè)涉及復(fù)雜需求的子請(qǐng)求的WebDAV請(qǐng)求時(shí),服務(wù)器需要一些時(shí)間來(lái)處理并發(fā)送此代碼“102–Processing”。此代碼旨在通過(guò)通知客戶(hù)端服務(wù)器收到請(qǐng)求并對(duì)其進(jìn)行處理來(lái)避免客戶(hù)端出現(xiàn)超時(shí)錯(cuò)誤。
總結(jié)
HTTP狀態(tài)碼的設(shè)計(jì)規(guī)則是:前面一位是分類(lèi)。2XX表示服務(wù)端已經(jīng)收到了請(qǐng)求,并且已經(jīng)分析處理完;3XX表示服務(wù)端已經(jīng)收到了請(qǐng)求,但是還需要其他資源或者服務(wù)處理;4XX表示服務(wù)端已經(jīng)收到了請(qǐng)求,但是無(wú)法理解,說(shuō)明客戶(hù)端請(qǐng)求姿勢(shì)不正確;5XX表示服務(wù)端已經(jīng)收到了請(qǐng)求,但是由于服務(wù)端自身問(wèn)題無(wú)法正確響應(yīng)。
這種編碼方法在很多地方都在用。
比如身份證號(hào)規(guī)則
前1、2位數(shù)字表示:所在?。ㄖ陛犑?、自治區(qū))的代碼;第3、4位數(shù)字表示:所在地級(jí)市(自治州)的代碼;第5、6位數(shù)字表示:所在區(qū)(縣、自治縣、縣級(jí)市)的代碼;第7—14位數(shù)字表示:出生年、月、日;第15、16位數(shù)字表示:所在地的派出所的代碼;第17位數(shù)字表示性別:奇數(shù)表示男性,偶數(shù)表示女性;第18位數(shù)字是校檢碼。
比如行別代碼
支付系統(tǒng)為每類(lèi)參與者分配一個(gè)標(biāo)識(shí)號(hào),由三位數(shù)字組成,第一位是銀行類(lèi)型,剩下兩位是標(biāo)識(shí)號(hào)。
支付系統(tǒng)的參與者行號(hào)規(guī)則和身份證規(guī)則很像,除了每幾位都有特殊含義,結(jié)尾一位也是驗(yàn)證碼。反正參與者行號(hào)規(guī)則我是記下來(lái)了。默念了8遍記下來(lái)的,真不容易。
聯(lián)系客服