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 | 由於臨時的服務器維護或者請求過載,服務器當前無法處理請求 |
知識很寶貴,就好像是金礦。學好知識,掌握好本領,會對我終身有益。請把努力當成一種習慣,而不是三分鍾熱度。每一個你羡慕的收獲,都是努力用心拼來的。