解析HTTP協議六種請求方法
1.GET
2.HEAD
3.PUT
4.DELETE
5.POST
6.OPTIONS
拋磚引玉,聊下概念性的東西先:
HTTP協議 (Hyper Text Transfer Protocol)
HTTP是一個基於TCP/IP通訊協議來傳遞資料,包括html檔案、影象、結果等,即是一個客戶端和伺服器端請求和應答的標準。
HTTP協議特點
1.http無連線:限制每次連線只處理一個請求,服務端完成客戶端的請求後,即斷開連線。(傳輸速度快,減少不必要的連線,但也意味著每一次訪問都要建立一次連線,效率降低)
2.http無狀態:對於事務處理沒有記憶能力。每一次請求都是獨立的,不記錄客戶端任何行為。(優點解放伺服器,但可能每次請求會傳輸大量重複的內容資訊)
3.客戶端/服務端模型:客戶端支援web瀏覽器或其他任何客戶端,伺服器通常是apache或者iis等
4.簡單快速
5.靈活:可以傳輸任何型別的資料
客戶端請求訊息
客戶端傳送一個請求到伺服器的請求訊息包括以下格式:
請求行,請求頭部,空行,請求資料 (圖片來自網路)
伺服器響應訊息
伺服器響應包括如下格式:
狀態行,訊息報頭,空行,響應正文
序號 | 方法 | 描述 |
---|---|---|
1 | GET | 傳送請求來獲得伺服器上的資源,請求體中不會包含請求資料,請求資料放在協議頭中。另外get支援快取、快取、可保留書籤等。冪等 |
2 | 和get一樣很常見,向伺服器提交資源讓伺服器處理,比如提交表單、上傳檔案等,可能導致建立新的資源或者對原有資源的修改。提交的資源放在請求體中。不支援快取。非冪等 | |
1 | GET | 傳送請求來獲得伺服器上的資源,請求體中不會包含請求資料,請求資料放在協議頭中。另外get支援快取、快取 |
1 | GET | 傳送請求來獲得伺服器上的資源,請求體中不會包含請求資料,請求資料放在協議頭中。另外get支援快取、快取 |
3 | HEAD | 傳送請求來獲得伺服器上的資源,請求體中不會包含請求資料,請求資料放在協議頭中。另外get支援快取、快取 |
4 | PUT | 和post類似,html表單不支援,傳送資源與伺服器,並存儲在伺服器指定位置,要求客戶端事先知道該位置;比如post是在一個集合上(/province),而put是具體某一個資源(/province/123)。所以put是安全的,無論請求多少次,都是在123上更改,而post可能請求幾次建立了幾次資源。冪等 |
5 | DELETE | 請求伺服器刪除某資源。和put都具有破壞性,可能被防火牆攔截。如果是https協議,則無需擔心。冪等 |
6 | CONNECT | HTTP/1.1協議中預留給能夠將連線改為管道方式的代理伺服器。就是把伺服器作為跳板,去訪問其他網頁 然後把資料返回回來,連線成功後,就可以正常的get、post了。 |
7 | OPTIONS | 獲取http伺服器支援的http請求方法,允許客戶端檢視伺服器的效能,比如ajax跨域時的預檢等。 |
8 | TRACE | 回顯伺服器收到的請求,主要用於測試或診斷。一般禁用,防止被惡意攻擊或盜取資訊。 |
GET 和 POST 比較
注意:以上只是一種規範,如果非要給get加上request body,或者給post的url上帶上引數,技術上沒有任何問題。
另外曾經看到一篇文章聽說『99% 的人都理解錯了 HTTP 中 GET 與 POST 的區別』??說,get傳送1個tcp包,而post傳送兩個tcp包,後來被驗證這個說法是不正確的,其實get如果也傳送body,則也會發送Expect:100
PATCH 和 PUT 比較
注意:比如更新一個userinfo,包含name,age,sex等多個欄位,如果只修改了age,如果用put來更新,則需要把其他沒有變更的也要提交到伺服器,但是使用patch,則只需要提交age到伺服器即可。這都是協議層面來討論的。
get
請求示例
GET https://testrail-tools.trendmicro.com/portal/admin/getTimerInitStatus HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Referer: https://testrail-tools.trendmicro.com/portal/admin/toLicenseTimerConfig?id=7
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: testrail-tools.trendmicro.com
Connection: Keep-Alive
Cookie: _ga=GA1.2.1909963682.1524537669; _gid=GA1.2.563928490.1529501401
以上對應
第1行 請求行
請求方法(get)+空格+url(https://testrail-tools.trendmicro.com/portal/admin/getTimerInitStatus)+空格+協議版本(HTTP/1.1)
第2-10都是請求頭部
Accept:表示客戶端接受的內容型別,按照先後順序表示客戶端接收資料的先後次序
X-Requested-With:以x開頭的是非http標準,一般是某種技術的出現而定義的;這裡是用來判斷是http請求還是ajax請求。
Referer:從這個頁面訪問請求行裡的url
Accept-Language:客戶端接受內容返回優先選擇的語言
Accept-Encoding:客戶端可以接受的伺服器對返回內容進行編碼壓縮的格式。
User-Agent:客戶端執行的瀏覽器型別資訊。
Host:頭域指定請求的伺服器的地址和埠,HTTP/1.1必須包括Host,否則返回400
Connection:表示是否需要持久連線。如果web伺服器端看到這裡的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1預設進行持久連線),它就可以利用持久連線的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點, web伺服器需要在返回給客戶端HTTP頭資訊中傳送一個Content-Length(返回資訊正文的長度)頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,然 後在正式寫出內容之前計算它的大小。
Cookie:http請求時,會把儲存的cookie也傳送伺服器。cookie是儲存在客戶端裡的,分為記憶體cookie和硬碟cookie。前者隨著瀏覽器關閉而消失,後者由過期時間或者使用者手動清除。因為http請求是無狀態的,所以伺服器為了認證,會生成sessionid,讓瀏覽器setcookie儲存起來,每次請求攜帶上認證資訊。這部份以後再聊吧。
響應示例
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: private
Expires: Wed, 31 Dec 1969 16:00:00 PST
X-Application-Context: application:prod
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Wed, 20 Jun 2018 15:00:16 GMT
{"advancewarn":"1","userstatus":"1","ldap":"1","licensealarm":"1","deltempzipfile":"1","sctmlicense":"0","user":"1"}
第1行 狀態行
第2-8 訊息報頭
Server:包含處理請求的伺服器資訊,包含多個產品註釋和標識。
Cache-Control:告知快取機制是否可以快取和型別,private是隻能當前使用者,不能被共享。
Expires:響應過期時間
X-Application-Context:application配置,這裡表示讀取的是application-prod.properties
Content-Type:返回資料的型別和字元編碼格式
Transfer-Encoding:告知接收端,報文采取了何種編碼,chunked表示伺服器無法確定訊息大小,一般比如下載等,就採用chunked。
Date:返回訊息的時間
第 9 行 空行
第 10 行 響應正文
訊息報頭指定了是返回json字串。
POST
請求示例
POST https://testrail-tools.trendmicro.com/portal/admin/editTimer HTTP/1.1
Host: testrail-tools.trendmicro.com
Connection: keep-alive
Content-Length: 35
Accept: application/json, text/javascript, */*; q=0.01
Origin: https://testrail-tools.trendmicro.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://testrail-tools.trendmicro.com/portal/admin/toAdminTimerConfig?id=7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA1.2.199305797.1501211992; _ga=GA1.1.199305797.1501211992; _gid=GA1.2.56449187.1529562439; _gat_gtag_UA_111346521_2=1
type=del&interval=1200&timelag=7200
第1行同 get
第2-13 行 請求頭部
Content-Length:告知伺服器,請求資料的大小
Origin:origin類似refered,但比refered更人性化,origin只出現在post中,而origin也不攜帶敏感資訊和具體url路徑。
Content-Type:http請求提交內容的編碼型別,一般只有post需要設定。application/x-www-form-urlencoded(預設)和multipart/form-data。
第14行 空行
第15行 請求資料
響應示例
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:prod
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 21 Jun 2018 07:36:58 GMT
{"result":"edit timer success"}
---------此處省略------------
結束語:其實我們大部分情況下只用到了GET和POST。如果想設計一個符合RESTful規範的web應用程式,則這六種方法都會用到。不過即使暫時不想涉及REST,
瞭解這六種方法的本質仍然是很有作用的。大家將會發現,原來web也是很簡潔明瞭的。下面再次依次說明這六種方法。
1,GET:GET可以說是最常見的了,它本質就是傳送一個請求來取得伺服器上的某一資源。資源通過一組HTTP頭和呈現據(如HTML文字,或者圖片或者視訊等)返回給客戶端。
GET請求中,永遠不會包含呈現資料。
2,HEAD:HEAD和GET本質是一樣的,區別在於HEAD不含有呈現資料,而僅僅是HTTP頭資訊。有的人可能覺得這個方法沒什麼用,其實不是這樣的。
想象一個業務情景:欲判斷某個資源是否存在,我們通常使用GET,但這裡用HEAD則意義更加明確。
3,PUT:這個方法比較少見。HTML表單也不支援這個。本質上來講, PUT和POST極為相似,都是向伺服器傳送資料,但它們之間有一個重要區別,
PUT通常指定了資源的存放位置,而POST則沒有,POST的資料存放位置由伺服器自己決定。舉個例子:如一個用於提交博文的URL,/addNew。
如果用PUT,則提交的URL會是像這樣的”/addNew/abc123”,其中abc123就是這個博文的地址。而如果用POST,則這個地址會在提交後由伺服器告知客戶端。
目前大部分部落格都是這樣的。顯然,PUT和POST用途是不一樣的。具體用哪個還取決於當前的業務場景。
4,DELETE:刪除某一個資源。基本上這個也很少見,不過還是有一些地方比如amazon的S3雲服務裡面就用的這個方法來刪除資源。
5,POST:向伺服器提交資料。這個方法用途廣泛,幾乎目前所有的提交操作都是靠這個完成。
6,OPTIONS:這個方法很有趣,但極少使用。它用於獲取當前URL所支援的方法。若請求成功,則它會在HTTP頭中包含一個名為“Allow”的頭,值是所支援的方法,如“GET, POST”。