本文屬於原創文章,轉載請註明--來自桃源小盼聊技術html
做爲一個程序員,當咱們訪問一個接口,服務器接收到並返回結果,那麼中間的流程是怎麼處理的呢?這個請求是如何到達服務器,服務器又是怎樣返回內容的?程序員
若是沒有HTTP協議,接口請求具體實現的細節, 都須要每一個客戶端和服務器各自約定和實現,而本身的規則,又不能適用於別人。這給開發帶來了極大的不便,HTTP就是爲此而設計的。HTTP協議用來約定雙方的行爲規範,讓相關開發者按照相同的規則來開發網站和工具。web
HTTP協議就像發快遞時填寫的發貨單,規定必須填寫收貨人,地址和手機號碼,只有這樣才能準確送給收貨人。HTTP則是規定了如何在兩臺電腦間發送和接收超文本。算法
1980年,蒂姆·伯納斯·李在CERN(歐洲核子研究組織)時,爲了方便各地研究人員共享信息,提出了一個設想,"藉助於超文本,鏈接成可互相瀏覽的WWW(萬維網)項目"。chrome
到了1989年,伯納斯·李看到了將超本文與互聯網結合的機會,那時已經有了在電腦上顯示信息的超文本系統,也有了域名系統和TCP/IP網絡傳輸協議。伯納斯·李又爲此設計製做世界上第一個網頁瀏覽器和網頁服務器,將這一切組合起來,就能實現瀏覽處於世界任何地方服務器上的超文本信息。在這個過程當中,因爲TCP/IP協議族中沒有適合傳輸超文本的協議,李博士又發起了HTTP(超文本傳輸協議)的提議。瀏覽器
因而在1989年,HTTP協議誕生了。現現在最普遍使用的協議版本是在1999年制定的HTTP 1.1。緩存
蒂姆·伯納斯·李在2017年4月5日,得到了2016年度圖靈獎,被譽爲萬維網之父。他發明了瀏覽器, HTTP,HTML,URI等一系列相關的萬維網技術。
安全
現實世界中的各行各業都有本身的行業規則,違反規則,步履艱難,而尊重規則,便如魚得水。網絡世界也須要各類各樣的規則,TCP/IP協議族就是這些規則的總稱。而HTTP協議是其中的一種,負責傳輸超文本(HyperText)。性能優化
TCP/IP協議族一共分爲四層,包含不一樣的協議。應用層、傳輸層、網絡層和鏈路層。服務器
這張圖簡單描述了,打開一個網站背後都發生了什麼?
客戶端發出請求報文,服務器收到請求,通過處理,把響應報文返回客戶端,鏈接斷開,一次請求結束。HTTP協議是無狀態協議。
在1990年W3C發佈了第一個HTTP/0.9版本,這個版本只支持GET請求。
1996年發佈了HTTP/1.0版本,這是第一個普遍使用的版本,支持了多媒體類型和各類HTTP首部字段。
但真正應用至今的是在1999年發佈的HTTP/1.1版本,它修復了一些結構的缺陷,並引入了性能優化的措施。本文如下的內容都以HTTP/1.1爲基礎展開。
咱們用chrome瀏覽器打開http://www.w3c.org
這個網站。打開開發者工具的network項,看看第一個請求的詳細信息。
請求報文由請求地址、請求方法、協議版本、首部字段和內容實體。
GET /index.html HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)
Host: w3c.org
複製代碼
響應報文由狀態碼及解釋短語、協議版本、首部字段和響應實體。
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 137582
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
複製代碼
HTTP/1.1 支持多種請求方法,最經常使用的仍是get和post方法。
HTTP通訊是創建在TCP鏈接的基礎上,早期版本每次通訊都須要從新鏈接、斷開TCP。因此在HTTP/1.1下,實現了在一次TCP鏈接中進行屢次HTTP通訊的能力,大大提升了服務器的響應速度。同時也支持並行發送請求,通常瀏覽器是支持同時6個鏈接。
gee方法是安全的請求方法,獲取已經存在的資源或者是查詢一些數據,一般會把請求參數拼接在url中。
head方法也是安全的,但它與get的不一樣在於,它不會返回響應實體內容,只返回響應首部。通常會用來確認請求url的有效性。
post方法會把請求內容放在請求實體中,而不是拼接在url中。因此通常查詢信息用GET方法,提交表單數據使用post方法。
查詢指定url資源支持的請求方法,例如支持get和head。
通常請求發出後,會通過多層代理服務器,這個方法就是用來確認請求發出後發生的一系列操做。但會引發跨站追蹤攻擊,通常不用。
put是用來往服務器上傳文件,而delete就是刪除服務器上的文件。可是這兩個方法沒有驗證機制,會產生不安全問題,通常服務器都不作支持。
狀態碼用來表示服務器返回的請求結果。由三位數字加解釋短語組成,例如 200 ok。 雖然狀態碼有不少,可是也可分門別類,並不須要掌握全部,也對返回的結果有個大體的瞭解。
狀態碼 | 響應類別 | 緣由短語 |
---|---|---|
1xx | 信息性狀態碼(Informational) | 服務器正在處理請求 |
2xx | 成功狀態碼(Success) | 請求已正常處理完畢 |
3xx | 重定向狀態碼(Redirection) | 須要進行額外操做以完成請求 |
4xx | 客戶端錯誤狀態碼(Client Error) | 客戶端緣由致使服務器沒法處理請求 |
5xx | 服務器錯誤狀態碼(Server Error) | 服務器緣由致使處理請求出錯 |
當咱們知道了,首位數字是定義狀態碼的類型後,理解更多的狀態碼也就簡單起來。 下面,再詳細介紹一些常見的狀態碼。
這個是最多見的,表示請求在服務器被正確處理了。
請求在服務器端被正確處理了,可是返回的響應報文中沒有實體內容。通常用在只是客戶端向服務器發送信息,而服務器不用向客戶端返回什麼信息的狀況。
永久性重定向,表明資源的連接已經更換了url,在響應報文中會包含新的連接地址。
當發出的請求中有附加條件(首部字段有if-*)時,服務器容許訪問,可是不知足條件的狀況。
請求報文內容存在語法錯誤,服務器處理不了。
發送的請求中含有HTTP認證信息,認證未經過。 返回401的響應必須包含一個適用於被請求資源的WWW-Authenticate首部以質詢用戶信息
請求的資源拒絕被訪問,通常是無權限訪問。
這個也很常見,請求的資源服務器找不到。
服務器在處理請求時,出錯了。通常是服務器發生了異常情況。
首部字段是爲了給瀏覽器和服務器提供報文主體大小、所使用的語言、認證信息等內容。通俗點講,瀏覽器和服務器會根據這些字段作出不一樣的反應,每一個字段至關於一條配置信息。 首部字段相似於鍵值對,請求報文和響應報文都包含首部信息。
這是一段請求首部字段,例如Accept表示瀏覽器能夠接受的響應報文實體類型。
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,ja;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Host:www.w3.org
If-Modified-Since:Thu, 04 May 2017 23:40:12 GMT
If-None-Match:"a384-54ebb4b41af00;89-3f26bd17a2f00-gzip"
複製代碼
首部字段分爲了五種類型,通用首部、請求首部、響應首部、實體首部和拓展首部。
類型 | 說明 |
---|---|
通用首部 | 是請求和響應都會用到的字段 |
請求首部 | 是客戶端向服務器發送請求時,報文中包含的首部字段 |
響應首部 | 是服務器向瀏覽器返回響應報文時,包含的首部字段 |
實體首部 | 是請求報文和響應報文中針對實體內容的首部字段 |
拓展首部 | 是非標準首部字段,由開發者根據自身需求自由定義和實現 |
如下列表,提供一些首部的簡單說明,每一個字段的具體使用都不同,實際應用仍是查看詳細介紹。
字段名 | 說明 |
---|---|
Cache-Control | 控制緩存行爲 |
Pragma | HTTP/1.0遺留字段,也是用於控制緩存機制 |
Transfer-Encoding | 傳輸報文主體的編碼方式 |
Trailer | 報文主體以後的首部字段,用於分塊傳輸 |
Upgrade | 檢測HTTP協議是否可用更高版本 |
Connection | 控制再也不轉發給代理的字段、鏈接的管理 |
Date | 建立報文的日期 |
Via | 追蹤客戶端與服務器之間報文的傳輸路徑,一般指代理服務器 |
Warning | 緩存相關警告 |
字段名 | 說明 |
---|---|
Accept | 客戶端可接受的媒體類型及相關優先級,q值表示權重 |
Accept-Charset | 客戶端可接受的字符集及優先順序 |
Accept-Encoding | 客戶端支持的內容編碼及優先順序 |
Accept-Language | 客戶端可處理的天然語言集,以及優先級 |
Authorization | 客戶端的認證信息,通常是證書信息 |
Host | 請求資源所在服務器的主機名和端口號 |
If-Match | 比較實體標記 |
If-Modified-Since | 比較資源更新時間 |
If-None-Match | 比較實體標記(與If-Match做用相反) |
If-Range | 資源未更新時發送實體Byte的範圍請求 |
If-Unmodified-Since | 比較資源更新時間(與If-Modified-Since做用相反) |
Max-Forwards | 最大傳輸逐跳數(TRACE或OPTIONS方法會用到) |
Range | 範圍請求的實體字節段 |
Referer | 請求頁面的原始url |
TE | 傳輸編碼及優先級 |
User-Agent | 請求客戶端的自身信息 |
字段名 | 說明 |
---|---|
Accept-Ranges | 服務器是否接受字節範圍請求 |
Age | 服務器響應建立通過的時間 |
ETag | 資源配置信息 |
Location | 服務器告知客戶端重定向url |
Proxy-Authorization | 代理服務器向客戶端發起的認證信息 |
Retry-After | 服務器告知客戶端再次請求的時間 |
Server | 服務器應用名、版本號等相關信息 |
Vary | 代理服務器的緩存管理信息 |
WWW-Authorization | 服務器對客戶端的認證信息 |
字段名 | 說明 |
---|---|
Allow | 資源支持的請求方法 |
Content-Encoding | 實體內容的編碼方式 |
Content-Language | 實體內容的天然語言集 |
Content-Length | 實體內容字節長度 |
Content-Location | 實體內容替代url |
Content-MD5 | 實體內容的報文摘要 |
Content-Range | 實體內容的位置範圍 |
Content-Type | 實體內容對應的媒體類型 |
Expires | 實體內容失效日期 |
Last-Modified | 實體內容最後修改日期 |
HTTP協議是無狀態的,若是咱們今天登陸了一個網站,明天從新打開網站時,能自動登陸,怎麼辦? 那就得靠cookie來解決了。它能在客戶端保存用戶的基本信息,當咱們下次訪問該網站,瀏覽器會把cookie一塊兒發送給服務器,服務器就會根據這些信息來判斷你是否登錄過。
cookie是網景公司的前僱員盧·蒙特利在1993年3月的發明的。cookie數據也是鍵值對的形式,它和網站以及網頁是關聯在一塊兒的。若是保存cookie值指定了網站地址,訪問其餘網站時並不會發送這些cookie值。
訪問一個網站,打開chrome的開發者工具,application中能夠看見cookie的信息。
HTTP協議傳輸的數據是明文未加密的,爲了安全性,網景公司設計了SSL協議(安全套接層),用SSL創建一個安全的通訊線路後,就能夠在這條線路上進行普通的HTTP通訊了,與SSL組合起來就是 HTTPS了,不過如今使用更多的是TLS(安全層傳輸協議)。
網站使用HTTPS須要申請一個證書,由第三方的可信賴機構提供的,這是爲了防止身份假裝。
接下來的通訊都將在此加密通訊下進行,以上任何確認過程失敗,都將斷開加密通訊。
看過錘子發佈會的,都知道這個組織,但具體幹什麼的恐怕也沒幾我的清楚。它是HTTPS中SSL和TLS的具體實現庫。 OpenSSL是一個開放源代碼的軟件庫包,應用程序可使用這個包來進行安全通訊,其主要庫是以C語言所寫成,實現了基本的加密功能,實現了SSL與TLS協議。OpenSSL能夠運行在絕大多數類Unix操做系統上,OpenVMS與 Microsoft Windows。
隨着互聯網的發展,web頁面的數據量暴增,服務多年的HTTP/1.1已經顯露疲態,因爲協議是固定的,因此瀏覽器,服務器和開發者等都經過各自的手段,來增強服務的響應能力,減緩HTTP/1.1的不足之處。
谷歌開發了SPDY這個實驗性協議來提高http的性能,HTTP/2的草案就是基於SPDY3.0展開的。HTTP/2的主要目標是改進傳輸性能,實現低延遲和高吞吐量。升級HTTP2不會影響原有的網站應用。
HTTP/2將全部傳輸的信息分割爲更小的消息和幀,並對它們採用二進制格式的編碼。以前版本的數據傳輸都是純文本的方式,二進制的解析更高效,更準確。這是整個HTTP/2性能提高的基礎。
當前問題:
HTTP/1.1協議中,一個tcp鏈接處理一個HTTP請求。例如同時有A和B兩個請求,先發送A請求,A請求響應結束,再發送B請求,若是A請求處理的時間很長,B也只能等待,這樣就形成了線頭堵塞。目前每一個瀏覽器能夠同時發起6-8個tcp鏈接,也依然不能很好地解決大量請求的處理。就算開啓了管道機制,一個tcp鏈接同時發送A和B請求,B仍是會等在A以後響應。
HTTP/2的方式:
HTTP/2中的請求都在一個tcp鏈接中處理,每一個請求和響應都被分解爲獨立的幀,而後並行交錯發送,再在另外一端從新組裝。請求之間再也不互相干擾,從而消除了沒必要要的等待和延遲,巨大地提高了性能。
因爲HTTP是無狀態的,因此每一次請求和響應都會攜帶頭信息,而其中不少頭信息是相同的,毫無疑問增長了傳輸的數據量。
因此HTTP/2設計了專門用於壓縮頭信息的HPACK算法,在客戶端和服務器端使用「首部表」來跟蹤和存儲以前發送的鍵值對,並進行更新替換。
當咱們訪問一個網頁時,服務器先返回HTML文檔,瀏覽器再根據這個文檔,去請求其中包含的圖片,樣式表和腳本。
而HTTP/2中,服務器能夠對一個客戶端發送多個響應,而無需客戶端再多起屢次請求,客戶端能夠控制該功能的開啓。