1、前言
好久沒寫部落格了,最近雖然沒什麼假期,但是卻比以前還忙!工作、工作、工作,就像趕集似的,聚在一起。對於Web開發人員來說,深入瞭解HTTP有助於我們開發出更好、更高的Web應用程式。當應用程式出現問題的時候也能夠很容易的找出並解決bug。
2、HTTP簡介
超文字傳輸協議(Hyper Text Transfer Protocol)協議,它是網際網路上應用最為廣泛的一種網路協議,即基於TCP/IP協議的應用層協議。其中最為常見的逛淘寶京東瀏覽網頁的過程,就是通過HTTP協議來傳遞瀏覽器與伺服器之間的請求與響應的。
從圖可以看出HTTP協議採用了請求/響應模型。當客戶端(通常是瀏覽器)發起HTTP請求,它首先會建立到HTTP伺服器指定埠(預設使用80埠)的TCP連線,而HTTP伺服器則負責在該埠監聽來自客戶端的請求。當TCP連線成功後瀏覽器會向HTTP伺服器傳送請求命令,如GET/api/SysBanner/BannerDetailsById。一旦收到請求,伺服器會根據請求向客戶端返回響應。響應內容通常有狀態(200 OK)以及很多訊息頭和訊息正文。正文就是資源呀、請求的檔案呀、錯誤資訊和其他資訊等等。
HTTP協議採用的是明文的協議,大溼兄就說了這種方式不安全,於是乎HTTPS它來了,HTTPS是啥呢,它是超文字傳輸安全協議(Hypertext Transfer Protocol Secure)也被稱之為HTTP over TLS,HTTP over SSL 反正我是記不清。後面有機會再聊聊HTTPS。
3、統一資源定位符
這個是啥呢?所謂統一資源定位符(Unifrom Resource Locator),就是URL說白了就是位址列那個東東。代表網路上一個特定的資源,用於標識並定位資源。
對於HTTP來講,當使用者在瀏覽器中書入了一個URL後,意味著他想要獲取或檢視一些資源種子,像圖片、HTML頁面、小電影、音樂、可執行檔案、office文件等等。要看妹子的圖片比如這個http://www.xxx.com/image/xxx.png。對於一個URL 如http://www.xxx.com/image/xxx.png它由以下部分組成。
a、http://,這個是URL協議,它指定了如何訪問一個特定的資源,如上慄中的http://會告訴瀏覽器使用http協議(文字傳輸協議),當然除了http://協議外還有https://(加密的http協議)、ftp://(檔案傳輸協議)、mailto:(電子郵件協議)等;
b、www.xxx.com,這是主機名,主機會告訴瀏覽器要訪問資源所在的伺服器名稱。DNS(Domain Name System)會將這個名稱解析魏具體的IP地址,通過IP再去訪問伺服器;
c、這是URL的路徑(Path),他指向的就是伺服器具體的資源,這一部分變化跟很大,有可能是檔案如上慄的www.xxx.com/image/xxx.png 也可以是動態、靜態網頁www.xxx.com/home/index。當訪問網頁的時候還包括圖片、JS檔案、CSS以及其他的資源;
d、埠號,在主機後面以英文冒號 : 隔開。一般來說都省略了只要是預設的80埠,伺服器在這個埠上監聽HTTP請求。通常在Web除錯中才會用到埠號 如http://www.xxx.com:8080;
e、查詢字串,這個就是引數部分。http://www.xxx.com/home/index?a=1&b=2 這裡的ab就是查詢的引數,如通過身份證查詢個人資訊通常get請求,多個引數用&分開。這些查詢字串都會傳送給HTTP伺服器;
f、錨部分、片段(Fagment),就是在#後面的部分,它用於指定資源特定的位置。這與上面的不通,它不會由伺服器處理,只會由瀏覽器定位到不用的位置,常見的VUE就是這種的 http://www.xxx.com/#/home。
由此可見一個完整的URL的格式如下
<protocol>://<host> [ : port ] / [ path ] [ ? query ] [ #fagment ]
4、媒體型別
當HTTP伺服器對請求返回響應的時候,它不僅返回資源本身還會在響應中指定資源的內容型別(Content Type),這就是媒體型別。要定製內容型別HTTP依賴於MIME(Multipurpose Internet Mail Extensions)標準,是一種表示文件的性質和格式的標準。MIME它最先用在電子郵件門後面HTTP協議也使用這一標準。瀏覽器通過MIME型別來決定如何處理文件。圖片就顯示。對於音訊、視訊檔案只有設定了正確的MIME型別才能被HTML語言中的<video>或者<audio>識別和播放。
當客戶端請求HTML頁面的時候HTTP伺服器會返回HTML內容,並且標識氣內容型別為text/html,前面的額text為主型別,後面的html是子型別。當請求一個圖片通常內容型別是image/gpeg或者image/gif。座椅MIME的型別合適很簡單type/subtype ,由主型別/子型別兩個字串組成,中間用“ / ” 號隔開,不允許空格哦。大小寫不敏感,傳統習慣性的都是小寫。常見的MIME型別如下
常見的MIME型別
型別 | 描述 | 示例 |
text | 普通文字 | text/plain、text/html、text/css、text/javascript |
image | 圖片 | image/gif、image/jpeg、image/png、image/bmp、image/webp |
audio | 音訊 | audio/midi、audio/webm、audio/ogg、audio/wav |
video | 視訊 | video/webm、video/ogg |
application | 二進位制資料等 | application/octet-stream、application/vnd.mspowerpoint、application/xml、application/pdf、application/json |
其中常見的MIME型別及其意義如下:
a、text/plain:內容就是純文字,瀏覽器認為可以直接顯示;
b、text/html:內容為html,即超文字標記語言,所有的HTML內容都是這樣的型別;
c、image/jpeg、image/png:這就是jpeg、png圖片;
d、application/json:表示json格式的資料,通常api現在介面大部分都是這個。
5、HTTP訊息
如果說客戶端發出的請求有問題或者伺服器上沒有請求的資源伺服器崩了呀,那麼就無法返回客戶端想要的結果。這個請求跟響應的過程中就像“對話”一樣。雙方(客戶端伺服器)都要理解對方的“語言”這就是HTTP訊息要解決的問題啦。當客戶端傳送請求到伺服器的時候,應該是用HTTP協議規定的格式的訊息;伺服器也會返回規定格式的響應。
HTTP請求訊息跟響應訊息都有相思的結構,如下。
a、起始行:就是第一行,用於描述請求或者是對應的狀態。成功與失敗了嘛,這個起始行總是單行哦;
b、HTTP訊息頭:描述了請求的或者響應的相關屬性、哦誒之、對正文訊息的描述等;
c、空行:說明訊息頭已經傳送完畢;
d、訊息正文:包含請求資料(創立的資源、HTML表單內容等),或者響應資源中的描述,這一部分可以為空不是必須的。
可以看出HTTP請求起始行包含以下內容
a、HTTP方法:如GET、POST、PUT等等描述要執行的動作 ;
b、請求目標:通常是一個URL,表示要訪問的資源;
c、HTTP版本:通常是HTTP/1.1。
HTTP響應起始行作為狀態行包括以下內容。
a、協議版本:通常HTTP/1.1;
b、狀態碼(Status Code):表示請求是否成功,常見的200(OK)、404(資源不存在)、500(伺服器錯誤)等等;
c、狀態文字(Status Text):一個簡短的文字資訊,用於描述狀態碼。
6、HTTP方法
HTTP定義了一組的請求方法來表示對指定資源執行的操作,每個請求都有一個HTTP請求方法,常見的有get、post、put、delete、patch、head、options等。
a、get:作用是用來獲取指定資源,它不會修改資源,所以他是安全的。它也是冪等的,所謂冪等就是多次對同一個URL呼叫同一個HTTP方法,其效果都是一樣的(你見過獲取產品列表會修改到資料庫嗎?);
b、post:它是用來建立資源的,因此他修改了伺服器的資源了(通常都是資料庫多一點)所以不是安全的,並且也不是冪等的;
c、put:它是更新資源的,也是修改了資源也不是安全的。但是它是冪等的,每次更新同一個資源返回的結果都是一樣的。跟post不一樣的是檔資源不存在的時候他還會建立資源;
d、delete:刪除資源也是不安全的,冪等的,如果資源不存在會返回404(NOt Found)狀態碼;
e:patch:更新區域性資源,跟put不一樣的是它只會更新區域性的欄位數形二put是全部更新;
f、head:它跟get差不多,但是它不返回訊息正文,只有訊息頭跟狀態碼,head主要該是用來檢測資源是否存在以及獲取資源的後設資料;
g、options:獲取資源支援的操作,伺服器返回響應中包含Allow訊息頭 如Allow:post , get。
一般情況來說我用的最多的就是post、get 我的api介面中基本都是這兩個哈哈。常見的HTTP方法總結如下
http方法總結
名 稱 | 作 用 | 安 全 | 冪 等 |
GET | 獲取資源 | 是 | 是 |
POST | 建立資源 | 否 | 否 |
PUT | 更新制定資源 | 否 | 是 |
DELETE | 刪除制定資源 | 否 | 是 |
PATCH | 根據區域性資源 | 否 | 否 |
HEAD | 與GET一樣但是沒有訊息正文 | 是 | 是 |
OPTIONS | 獲取資源支援的操作 | 是 | 是 |
7、HTTP訊息頭
無論是請求跟響應中都有訊息頭,用來傳遞附加資訊。一個訊息頭由名稱跟值組成中間用 : 冒號隔開,如Content-Type:text/plain。HTTP請求與響應中均包含可以多個訊息頭。如下微信請求的封裝類新增的請求訊息頭。
/// <summary> /// 微信請求Post /// </summary> /// <param name="url">地址</param> /// <param name="requestString">引數</param> /// <param name="merchantIdPwd">商戶號密碼</param> /// <param name="merchantId">商戶號</param> /// <param name="cardPath">證照路徑</param> /// <param name="serialNo">商戶證照號</param> /// <returns></returns> public async Task<string> WeChatPostAsync(string url, string requestString, string merchantIdPwd, string merchantId, string cardPath, string serialNo) { try { var client = _httpClientFactory.CreateClient(); var requestContent = new StringContent(requestString); requestContent.Headers.ContentType.MediaType = "application/json"; var auth = BuildAuthAsync(url, requestString, merchantIdPwd, merchantId, serialNo, cardPath, "POST"); string value = $"WECHATPAY2-SHA256-RSA2048 {auth}"; client.DefaultRequestHeaders.Add("Authorization", value); client.DefaultRequestHeaders.Add("Accept", "application/json"); client.DefaultRequestHeaders.Add("User-Agent", "WOW64"); client.Timeout = TimeSpan.FromSeconds(60); var response = await client.PostAsync(url, requestContent); if (response.IsSuccessStatusCode) { var result = await response.Content.ReadAsStringAsync(); return result; } else { return $"介面【{url}】請求錯誤,錯誤程式碼{response.StatusCode},錯誤原因{response.ReasonPhrase}具體的話========================================\n{JsonConvert.SerializeObject(response)}"; } } catch (Exception ex) { SaveLog($"介面【{DateTime.Now + url}】請求錯誤,錯誤程式碼{ex.Message}具體=============================================/n{ex.StackTrace}"); throw new Exception(ex.Message + ex.StackTrace); } }
常見的請求訊息頭
訊息頭 | 說 明 | 示 例 |
Accept | 可接受的響應內容型別(Content-Type) | Accept:application/json |
Acceept-Charset | 可接受的字符集 | Acceept-Charset:utf-8 |
Accept-Encoding | 可接受響應內容編碼方式 |
Content-Encoding:gzip
|
Accept-Language | 可接受響應內容語言列表 | Accept-Language:en-US |
Authorization | 用於HTTP協議中需要認證資源的認真資訊 | Authorization:basic JWT字元 |
Cache-Control | 用來指定丁前請求中是否使用快取 | Cache-Control:no-cache |
Connection | 客戶端(瀏覽器)想要優先使用的連線方式 | Connection:keep-alive |
Cookie | 向伺服器提供Cookie | Cookie:name=value;name2=value2 |
Content-Length | 請求正文的長度 | Content-Length:2048 |
Content-Type | 請求正文中的MIME型別(POST或者PUT請求中) | Content-Type:application/json |
Date | 傳送該訊息的日期和時間 |
Date:Fri, 08 Oct 2021 14:50:00 GMT
|
Host | 伺服器的主機以及使用的埠號 | HOST:www.xx.com |
If-Match | 當客戶端的值與伺服器上面的對應起來才進行相關操作 | If-Match:ADGJMPDW |
If-Modified-Since | 允許資源被修改是返回304NOt Modified狀態碼 | If-Modified-Since:Fri, 08 Oct 2021 14:50:00 GMT |
If-None-Match | 當伺服器任何資源和服務端提供的值不匹配,伺服器才會返回資源 | If-None-Match:ADGJMPDW |
If-Unmodified-Since | 僅當資源某個特定時間以來沒有修改的時候才傳送響應 | If-Unmodified-Since:Dec,26 Dec 2021 23:4533 GMT |
Orgin | 用於發起一個跨域請求 | Orgin:http://www.xxx.com |
Proxy-Authorization | 用於向代理進行認證的認證資訊 | Proxy-Authorization: base jwt字串 |
User-Agent | 瀏覽器身份識別符號 |
User-Agent:Mozilla/5.0...
|
常見的響應訊息頭
訊息頭 | 說 明 | 示 例 |
Allow | 指明資源支援的有效操作 | Allow:GET,POST |
Cache-Control | 指明該響應使用快取機制 | Cache-Control:max-age=3600 |
Connection | 針對該連線做預期的選項 | Connection:close |
Content-Encoing | 響應正文使用的編碼型別 | Content-Encoing:gzip |
Content-Language | 響應正文使用的語言型別 | Content-Language:zh-cn |
Content-Length | 響應正文的長度 | Content-Length:1024 |
Content-Type | 響應正文的MIME型別 | Content-Type:text/html;chartset=utf-8 |
Date | 訊息被髮送時的日期和時間 | Date:Fri, 08 Oct 2021 14:50:00 GMT |
ETag | 資源當前狀態的一個識別符號 | ETag:"gikif8f8f68f6ftyjy" |
Expires | 指定一個時間,預設過了這個時間認為響應已經過期 | Expires:Date:Fri, 08 Oct 2021 14:50:00 GMT |
Last-Modified | 請求資源最後修改的日期 | Last-Modified:Date:Fri, 08 Oct 2021 14:50:00 GMT |
Location | 指向另一個URL用於進行重定向,成功建立資源是使用 | Location:https://www.xxx.com/api/auther/1234 |
Proxy-Authenticate | 要求訪問代理是提供身份認證資訊 | Proxy-Authenticate:basic |
Server | 伺服器名稱 |
Server:Kestrel 或者 Server:nginx/1.18.0或者Server:Microsoft-IIS/10.0
|
Set-Cookie | 設定HTTP Cookie | Set-Cookie:UId=123,Age=18;Version:1.0 |
WWW-Authenticate | 表示請求應使用的認證方式 | WWW-Authenticate:Basic |
8、HTTP狀態碼
HTTP的響應狀態碼由3個數字組成,表示請求的結果,狀態碼後面有文字簡單說明狀態的資訊。如200 OK、404 Not Found、500 Internet Server Error等等。狀態碼可以分為一下5類。
a、1xx:資訊,伺服器收到請求啦,需要對面繼續執行操作;
b、2xx:成功,伺服器成功執行客戶端所請求的操作;
c、3xx:重定向,需要進一步的操作完成(通常我遇到的都是304);
d、4xx:客戶端錯誤,需要檢查程式碼或者請求內容不正確;
e、5xx:服務端錯誤,伺服器在處理請求過程中出現了錯誤 通常500 最常見。
常見的HTTP狀態碼
狀態碼 | 狀態碼名稱 | 描 述 |
200 | OK | 請求操作執行成功,並且返回包含預期的資源 |
201 | Created | 資源建立成功,響應正文為空 |
202 | Accepted | 已接收請求,開始執行非同步,但是處理還沒有完場 |
204 | No Content | 請求資源成功,響應正文為空 |
301 | Moved Permanently | 請求的資源被永久移動,響應訊息中應包含新的資源URL,瀏覽器會自動重定向到新的URL |
303 | See Other | 對當前請求的響應可以再另一個URL上被找到,該URL在當前響應的Location訊息頭中 |
304 | Not Modified | 所請求的資源未修改,客戶端可以從快取中得到資源,服務端返回該狀態碼事,訊息正文不包含任何內容(與204 NOt Content 一樣) |
307 | Temporary Redirect | 服務端不處理客戶端的請求,客戶端應向另一個URL請求,該URL在當前響應的Location訊息頭中 |
400 | Bad Request | 客戶端請求存在錯誤,程式碼錯誤,服務端無法理解 |
401 | Unauthorized | 當前請求要訪問受保護的資源,沒有像服務端提供正確的認證資訊或者就沒有提供任何認證資訊 |
403 | Forbidden | 當請求受保護的資源時,儘管提供了正確的認證資訊,但是許可權不夠禁止訪問該資源 |
404 | Not Found | 請求資源不存在 |
405 | Method Not Allowed | 請求的資源不支援客戶端指定的的HTTP方法,該響應頭中必須包含Allow項,用於表示當前資源能夠接收的請求方法列表 |
406 | Not Acceptable | 伺服器不支援請求中指定的資源表述格式(Accept訊息頭指定,請求json你用image/png怎麼可能) |
409 | Confict | 請求資源衝突,請求無法完成農,通常是put請求處理衝突 |
412 | Precondition Failed | 客戶端請求頭重指定了一個或者多個先決條件,伺服器無法驗證這些先決條件失敗 |
415 | Unsupperted Media Type | 請求中使用了伺服器不支援的資源表述格式(由Content-Type決定) |
500 | Internet Server Error | 伺服器內部錯誤,無法處理請求(伺服器崩了,當機) |
503 | Service Unavailable | 由於臨時的伺服器維護或者請求過載,伺服器當前無法處理請求 |
知識很寶貴,就好像是金礦。學好知識,掌握好本領,會對我終身有益。請把努力當成一種習慣,而不是三分鐘熱度。每一個你羨慕的收穫,都是努力用心拼來的。