HTTP全解析
一.Http是什么?
中文名稱--超文本傳輸協議,是TCP/IP協議族的最頂層-應用層。
二.Http請求格式
URL格式分為三部分:
協議類型://服務器地址(和端口號)/路徑(Path)
https://segmentfault.com/writ...
三.Http的報文格式
1.請求:
- 請求報文---->分為 : 請求行,Header,Body三部分。
- 請求行中包括請求的方式(GET,POST等),請求的路徑(主機地址之后的部分),Http的版本號
- 請求頭包括一些上傳信息的屬性,是固定名稱的鍵值對形式,最后一個請求頭之后是一個空行,這個行非常重要,它表示請求頭已經結束,接下來的是請求正文。
- 請求體是上傳的內容,一般配合請求頭Content-Type為 x-www-form-urlencoded的形式使用(表單格式),GET請求沒有請求體。
2.響應:
- 響應報文---->分為:響應行,Header,Body三部分。
- 響應行中包括Http版本號,響應狀態碼和響應狀態信息三部分。
- 響應體根據服務器返回的數據格式為主,一般響應體都是返回JSON格式。
四.請求方法:列舉常見的5種
理論上講 GET POST 除了這兩個詞不一樣之外沒有任何區別。區別都是客戶端的約定俗成,以下均是在HTTP以標準規范使用的情況下為基礎。
GET
- 用于直接從服務器上獲取資源。
- 對服務器數據不進行修改,滿足冪等性(反復調用多次時會得到相同的結果。例如執行十次相同的GET請求相當于從服務器獲取十次數據,但并不會對服務器數據造成修改)。
不發送Body請求體。
GET /users/1 HTTP/1.1 Host: api.github.comPOST
- 用于增加或修改服務器上的資源。
- 發送給服務器的內容寫在Body中。
- 不滿足冪等性(增加資源的時候執行一次和執行十次不同,執行一次增加一個,執行十次增加十個)。
PUT
- 用于修改服務器上的資源(和POST請求功能有些重復了,POST既能新增又能修改資源,PUT只能修改資源)。
- 發送給服務器的內容寫在Body中。
- 滿足冪等性。
DELETE
- 用于刪除服務器上的資源。
- 不發送BODY。
HEAD
- 和GET請求一樣都是從獲取資源(和GET請求不同的是響應數據中沒有BODY)。
- 一般可以用于下載文件,比如先用HEAD請求去看是否支持服務器是否支持分段下載功能,如果支持再用GET或POST請求配置相應分段傳輸的數據去下載獲取資源,避免無用的資源浪費。檢查資源的有效性(如先用HEAD拉去獲取ACCEPT RANGE總長度,再用GET請求配合RANGE去下載部分內容)。
五.Status Code狀態碼
用于對相應結果作出類型化描述。
- 1xx:臨時性消息。如:100 (繼續發送)、101(正在切換協議)
- 2xx:成功。最典型的是 200(OK)、201(創建成功)。?
- 3xx:重定向。如 301(永久移動)、302(暫時移動)、304(內容未改變)。 301表示搜索引擎在抓取新內容的同時也將舊的網址交換為重定向之后的網址;302表示舊地址A的資源還在(仍然可以訪問),這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址(瀏覽器緩存的地址)。
- 4xx:客戶端錯誤。如 400(客戶端請求錯誤)、401(認證失敗)、403(被禁止)、404(找不到內容)。? 401配合Authorization,403比如IP被禁止,404比如傳的URL錯誤
- 5xx:服務器錯誤。如 500(服務器內部錯誤)。
六.Header
1.Header是什么?
HTTP消息的metadata(元數據)。
2.什么是元數據?
通俗的講就是數據的屬性。以一個登錄接口為例,用戶名密碼是上傳的數據(放在BODY中),那么用戶名密碼的長度( Content-Length)、以什么類型( Content-Type )上傳等等就是它的元數據。
幾個重要的Header:
1.Host
目標主機。注意:不是在網絡上用于尋址(尋址用DNS)的,而是在目標服務器(找到IP后一個IP下有可能有多個主機名,確定訪問的是哪一個主機)上用于定位子服務器的。
2.Content-Type
指定Body的類型。主要分為四類:
(1). text/html: 請求 Web 頁面是返回響應的類型,Body 中返回 html文本。格式如下:
HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 Content-Length: 853 ......<!DOCTYPE html> <html> <head><meta charset="utf-8"> .....(2). x-www-form-urlencoded : 純文本表單的提交方式(只有以表單形式提交時,才會讀取Body中的內容)。 格式如下:
POST /users HTTP/1.1Host: api.github.com Content-Type: application/x-www-form-urlencoded Content-Length: 27 name=lvzishen&gender=male對應 Retrofit 的代碼:
@FormUrlEncoded <--代表的是以普通表單(application/x-www-form-urlencoded)上傳文本參數,加了這個注解后才會讀取@Field中的參數,因為@Field最后會轉變為請求體Body中的內容. @POST("/users") Call addUser(@Field("name") String name, @Field("gender") String gender);(3).multipart/form-data :頁面含有二進制文件時的提交方式(上傳文件或文字都可以,但是一般沒有用此上傳純文字,因為會多加如boundary、分隔符等字符,浪費流量和帶寬)。(只有以表單形式提交時,才會讀取Body中的內容)。 格式如下:
POST /users HTTP/1.1 Host: hencoder.com Content-Type: multipart/form-data; boundary=---- boundary為起始點 WebKitFormBoundary7MA4YWxkTrZu0gW Content-Length: 2382 ------WebKitFormBoundary7MA4YWxkTrZu0gW WebKitFormBoundary7MA4YWxkTrZu0gW<--為分隔符 Content-Disposition: form-data; name="name" rengwuxian ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="avatar"; filename="avatar.jpg" Content-Type: image/jpeg JFIFHHvOwX9jximQrWa......(4). application/json , image/jpeg , application/zip ...
單項內容(文本或非文本都可以),用于 Web Api 的響應或者 POST / PUT 的請求
請求中提交 JSON:
響應中返回JSON:
HTTP/1.1 200 OKcontent-type: application/json; charset=utf-8 content-length: 234[{"login":"mojombo","id":1,"node_id":"MDQ6VXNl cjE=","avatar_url":"https://avatars0.githubuse rcontent.com/u/1?v=4","gravat......image/jpeg:提交或獲取圖片
POST /user/1/avatar HTTP/1.1 Host: hencoder.com Content-Type: image/jpeg Content-Length: 1575 JFIFHH9......3.Content-Length
指定 Body 的長度(字節)。用于二進制文件中的長度讀取,因為不能確定讀取到哪里,所以規定長度,讀取到對應長度后代表讀取完成不再讀取。
4.Transfer: chunked (分塊傳輸編碼 Chunked Transfer Encoding)
用于當響應發起時,內容長度還沒能確定的情況下。和 Content-Length 不同時使用。用途是盡早給出響應,減少用戶等待。
HTTP/1.1 200 OK Content-Type: text/html Transfer-Encoding: chunked4 Chun <--不斷給出數據 先給4字節的Chun,再給9字節的ked Trans,.....,0代表傳輸完成全部加載完畢。 9 ked Trans 12 fer Encoding 05.Location
指定重定向的目標的URL
6.User-Agent
用戶代理,即是誰實際發送請求、接受響應的,例如手機瀏覽器、某款手機 App。
7.Range / Accept-Range
按范圍取數據
- Accept-Range: bytes 響應報文中出現,表示服務器支持按字節來取范圍數據
- Range: bytes =<start>-<end> 請求報文中出現,表示要取哪段數據
- Content-Range:<start>-<end>/total 響應報文中出現,表示發送的是哪段數據
作用:斷點續傳、多線程下載。
8.Cache
作用:在客戶端或中間網絡節點緩存數據,降低從服務器取數據的頻率,以提高網絡性能。
9.Cookie
10.Authorization
(1)Basic
格式:Authorization: Basic username:password(Base64ed) 對用戶名密碼做Base64編碼,不是加密的,Base64只是編碼。
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==(2)Bearer
格式:Authorization: Bearer token
bearer token 的獲取方式:
通過 OAuth2 的授權流程 OAuth2 的流程
為什么 OAuth 要引入Authorization code,并需要申請授權的第三方將 Authorization code 發送回自己的服務器,再從服務器來獲取 access token,而不是直接返回 access token ?這樣復雜的流程意義何在?
答:為了安全。OAuth 不強制授權流程必須使用 HTTPS,因此需要保證當通信路徑中存在竊聽者時,依然具有足夠的安全性。
在自家 App 中使用 Bearer token
有的 App 會在 Api 的設計中,將登錄和授權設計成類似 OAuth2 的過程,但簡化掉 Authorization code 概念。即:登錄接收請求成功時,會返回 access token,然后客戶端在之 后的請求中,就可以使用這個 access token 來當做 bearer token 進行用戶操作了。 (這么做失去了使用OAuth2的意義)
Refresh token 用法:access token 有失效時間,在它失效后,調用 refresh token 接口,傳入efresh_token 來獲取新的 access token。
{ "token_type": "Bearer", "access_token": "xxxxx", "refresh_token": "xxxxx", "expires_time": "xxxxx" }目的:安全。
當 access token 失竊時,由于它有失效時間,因此壞人只有較短的時間來「做壞事」;同時,由于(在標準的 OAuth2 流程中)refresh token 永遠只存在與第三方服務的服務 器中,因此 refresh token 幾乎沒有失竊的風險。
七.RESTful是什么?
以HTTP標準協議去使用HTTP。
比如:
八.HTTP1.0 HTTP 1.1主要區別
一.長連接 Keep-Alive
HTTP 1.0需要使用keep-alive參數來告知服務器端要建立一個長連接,而HTTP1.1默認支持長連接。Connection:keep-alive(雖然是不斷開但是每次也只能串行的執行HTTP請求,2.0才支持并行)
HTTP是基于TCP/IP協議的,創建一個TCP連接是需要經過三次握手的,有一定的開銷,如果每次通訊都要重新建立連接的話,對性能有影響。因此最好能維持一個長連接,可以用個長連接來發多個請求。
持久連接的時間參數,通常由服務器設定,比如 nginx 的 keepalivetimeout,keepalive timout 時間值意味著:一個 http 產生的 tcp 連接在傳送完最后一個響應后,還需要 hold 住 keepalive_timeout (通常為5-15S)秒后,才開始關閉這個連接;
二.節約帶寬
HTTP 1.1支持只發送header信息(不帶任何body信息),如果服務器認為客戶端有權限請求服務器,則返回100,否則返回401。客戶端如果接受到100,才開始把請求body發送到服務器。
這樣當服務器返回401的時候,客戶端就可以不用發送請求body了,節約了帶寬。
另外HTTP還支持傳送內容的一部分。這樣當客戶端已經有一部分的資源后,只需要跟服務器請求另外的部分資源即可。這是支持文件斷點續傳的基礎。
三.HOST域
現在可以web server例如tomat,設置虛擬站點是非常常見的,也即是說,web server上的多個虛擬站點可以共享同一個ip和端口。
HTTP1.0是沒有host域的,HTTP1.1才支持這個參數。
九.HTTP1.1 HTTP 2.0主要區別
一.多路復用的單一長鏈接
1.單一長連接
在HTTP/2中,客戶端向某個域名的服務器請求頁面的過程中,只會創建一條TCP連接,即使這頁面可能包含上百個資源。 單一的連接應該是HTTP2的主要優勢,單一的連接能減少TCP握手帶來的時延 。HTTP2中用一條單一的長連接,避免了創建多個TCP連接帶來的網絡開銷,提高了吞吐量。
2.多路復用
HTTP2雖然只有一條TCP連接,但是在邏輯上分成了很多stream。
HTTP2把要傳輸的信息分割成一個個二進制幀,首部信息會被封裝到HEADER Frame,相應的request body就放到DATA Frame,一個幀你可以看成路上的一輛車,只要給這些車編號,讓1號車都走1號門出,2號車都走2號門出,就把不同的http請求或者響應區分開來了。但是,這里要求同一個請求或者響應的幀必須是有有序的,要保證FIFO的,但是不同的請求或者響應幀可以互相穿插。這就是HTTP2的多路復用,是不是充分利用了網絡帶寬,是不是提高了并發度?
二.Header數據壓縮
HTTP1.1不支持header數據的壓縮,HTTP2.0使用HPACK算法對header的數據進行壓縮,這樣數據體積小了,在網絡上傳輸就會更快。
相當于建立一個映射表,如GET方法直接定義為映射表中的數字2,那么GET請求時請求方法寫2就可以而不用寫GET,這樣就可以節省流量和空間。
三.服務器推送
這個功能通常被稱作“緩存推送”。主要的思想是:當一個客戶端請求資源X,而服務器知道它很可能也需要資源Z的情況下,服務器可以在客戶端發送請求前,主動將資源Z推送給客戶端,這樣當使用Z資源時就不用請求網絡直接本地取數據就可以了,加快獲取速度。
總結
- 上一篇: 我的2018总结
- 下一篇: TiKV 源码解析系列文章(二)raft