http請求方法
請求方法的含義
- GET
The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
get方法請求指定的資源.get請求應該僅僅用去獲取數據
HEAD
The HEAD method asks for a response identical to that of a GET request, but without the response body.
head方法期望得到與get方法相同的響應,但響應體
POST
The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server
post方法用于將實體提交給指定的資源,通常會導致服務器上狀態的改變,或產生副作用。
PUT
The PUT method replaces all current representations of the target resource with the request payload.
put使用有效的請求去替換目標資源的當前狀態(用客戶端發送的數據去替換服務器端的數據)
put方法用
DELETE
The DELETE method deletes the specified resource.
delete方法用于刪除指定的資源
CONNECT
The CONNECT method establishes a tunnel to the server identified by the target resource.
connect方法建立起由目標資源標識到服務器端的隧道
OPTIONS
The OPTIONS method is used to describe the communication options for the target resource.
options方法用于描述目標資源的通信選項。
TRACE
The TRACE method performs a message loop-back test along the path to the target resource.
trace方法沿著目標資源的路徑執行消息環回測試。
PATCH
The PATCH method is used to apply partial modifications to a resource.
patch方法用于對資源進行部分修改。
這里著重強調一下我們比較常用的get方法和post方法的區別
含義
get:用于向服務器請求資源
post:向服務器發送實體數據傳遞數據的方式不同(當傳遞數據時)
get:將數據連接在url地址后面通過?進行分隔
post:將數據放在請求體中效率
get 更簡單也更快安全性
由于get方法將發送給服務器的信息直接加載url之后,相比post的將信息放在http報文主體上便顯得更加不安全緩存
get請求默認會被緩存,默認的請求方式也是有緩存的,所以我們在用get方法請求同一資源的時候如果希望每次請求的資源都是從服務器端獲取的最新資源而不是緩存的資源時,往往會通過在url后面加上&rand=Math.random()
使得每次發送的url地址不完全相同來保證能每次都從服務器上獲取資源
post由于post方法主要是為了向服務器傳送數據,雖然對同一資源傳遞數據時url每次都相同,但是http報文的請求體中的數據往往不相同,所以緩存也沒什么用,所以瀏覽器一般默認不緩存除非主動去設置數據發送量
get請求對發送的數據量會有限制
post請求對發送的數據量往往不會有太大限制
對于請求方式的知識,通過以上的小結,或許你覺得自己已經了解得差不多了,那么問題來了?
- get請求為什么會比post請求更快呢?
- 能否把get請求都換成post?把post換成get呢?
是否陷入了沉思?是的,前面的那點點知識還不夠用,讓我們接著往后看~
其實GET和POST本質上并沒有什么區別。
get和post僅僅知識http協議中的兩種請求方法,而http是基于TCP/IP的關于數據如何在萬維網中如何通信的協議。
HTTP的底層是TCP/IP。所以GET和POST的底層也是TCP/IP,也就是說,GET/POST都是TCP鏈接。GET和POST能做的事情是一樣一樣的。你要給GET加上request body,給POST帶上url參數,技術上是完全行的通的。
那么,“為什么會出現前面那些,我們自以為是的“正確答案”呢?
在萬維網世界中,TCP就像汽車,我們用TCP來運輸數據,它很可靠,從來不會發生丟件少件的現象。但是如果路上跑的全是看起來一模一樣的汽車,那這個世界看起來是一團混亂,送急件的汽車可能被前面滿載貨物的汽車攔堵在路上,整個交通系統一定會癱瘓。為了避免這種情況發生,交通規則HTTP誕生了。HTTP給汽車運輸設定了好幾個服務類別,有GET, POST, PUT, DELETE等等,HTTP規定,當執行GET請求的時候,要給汽車貼上GET的標簽(設置method為GET),而且要求把傳送的數據放在車頂上(url中)以方便記錄。如果是POST請求,就要在車上貼上POST的標簽,并把貨物放在車廂里。當然,你也可以在GET的時候往車廂內偷偷藏點貨物,但是這是很不光彩;也可以在POST的時候在車頂上也放一些數據,讓人覺得傻乎乎的。HTTP只是個行為準則,而TCP才是GET和POST怎么實現的基本。
但是,我們只看到HTTP對GET和POST參數的傳送渠道(url還是requrest body)提出了要求。“標準答案”里關于參數大小的限制又是從哪來的呢?
在我大萬維網世界中,還有另一個重要的角色:運輸公司。不同的瀏覽器(發起http請求)和服務器(接受http請求)就是不同的運輸公司。 雖然理論上,你可以在車頂上無限的堆貨物(url中無限加參數)。但是運輸公司可不傻,裝貨和卸貨也是有很大成本的,他們會限制單次運輸量來控制風險,數據量太大對瀏覽器和服務器都是很大負擔。業界不成文的規定是,(大多數)瀏覽器通常都會限制url長度在2K個字節,而(大多數)服務器最多處理64K大小的url。超過的部分,恕不處理。如果你用GET服務,在request body偷偷藏了數據,不同服務器的處理方式也是不同的,有些服務器會幫你卸貨,讀出數據,有些服務器直接忽略,所以,雖然GET可以帶request body,也不能保證一定能被接收到哦。
好了,現在你知道,GET和POST本質上就是TCP鏈接,并無差別。但是由于HTTP的規定和瀏覽器/服務器的限制,導致他們在應用過程中體現出一些不同。
GET和POST的區別????????
GET和POST還有一個重大區別,簡單的說:
GET產生一個TCP數據包;POST產生兩個TCP數據包。
長的說:
對于GET方式的請求,瀏覽器會把http header和data一并發送出去,服務器響應200(返回數據);
而對于POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
也就是說,GET只需要汽車跑一趟就把貨送到了,而POST得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然后再回頭把貨送過去。
因為POST需要兩步,時間上消耗的要多一點,看起來GET比POST更有效。因此Yahoo團隊有推薦用GET替換POST來優化網站性能。但這是一個坑!跳入需謹慎。為什么?
- GET與POST都有自己的語義,不能隨便混用。
- 據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的TCP在驗證數據包完整性上,有非常大的優點。
- 并不是所有瀏覽器都會在POST中發送兩次包,Firefox就只發送一次。
在深入的了解了http協議的兩種請求方法之后我想,讓我們在來回顧一次前面的問題
- get請求為什么會比post請求更快呢?
準確的說是多數情況下比較快,關鍵還是得看我們的瀏覽器大哥喜歡怎么做。對于大多數瀏覽器來說由于get請求一次性將header和data一起發送即只發送一次包,而post發送兩次數據包,第一次發送header,等服務器返回100 continue后在發送第二次數據包,將data發送給服務器。一次發送跟兩次發送,很明顯get會更加效率一些。 - 能否把get請求都換成post?把post換成get呢?
我的答案是萬萬不能。
萬事萬物的存在的原因。對于http協議上的get和post方法更是如此,沒有人會無聊到能用一個方法就實現的東西偏偏要弄出兩種方法來讓其更加復雜。而我們想理解背后的原因,我覺得最好的方法便是結合實際的應用場景(畢竟http協議的產生的目的說到底還是為了更好的解決現實問題)
場景:
----------------摘自《圖解HTTP》
對于get請求,我們從文章開頭的定義中知道,其目的僅僅是為了獲取資源,并不是為了傳送數據,所以即使要傳送數據,也要將數據放在了get請求的url后面,而服務器對其的處理更是直接從url上直接解析,以了解用戶需要的資源,再決定是否將資源傳給用戶。針對以上的描述,我們不難知道其實對于get請求確實只發送一次包就足夠了,發送兩次包實毫無意義的。
而對于post請求,其最主要的目的是為了向服務器發送數據,并引起服務器端數據或狀態的某些改變。服務器在接到數據并處理之后返回處理后的結果給客戶端。現在讓我們結合上面的圖來思考一種情況,如果說客戶端指定的資源的訪問和修改是需要進行認證的。而我們的post請求不是發送兩次包,一次發送頭部,一次發送data,會是發生什么?----瀏覽器一次性將header和data一起發送,而服務器卻因為該用戶還沒進行認證或者是不具備訪問權限,而不能接收用戶的數據進行處理,這樣的話豈不是浪費的大量的網絡資源,但是如果是兩次發送就不同了,當第一個包發送的時候,服務器經過檢驗知道用戶具有訪問響應資源的權限,發送響應報文將頭部設為100 continue,讓瀏覽器發送后續的data,而如果是還沒認證便發送401 Unauthorized讓用戶進行先認證,認證成功后才讓瀏覽器發送數據,這樣是便很好的解決了前面說提到的問題。
前兩張圖是我分別通過post方法和get方法分別進行數據的發送后從瀏覽器中看到的, 可見,瀏覽器對于get和post發送數據的處理方式并不相同,從而也開始懷疑瀏覽器在發送get請求的時候是否真的會將沒有數據的body也發送了,便通過以下代碼進行了嘗試
$(function (){ $("#myform").on('submit',function (event){ event.preventDefault(); var data = $(this).serialize(); /* $.ajax({ method:"POST", url:"/mytest", data:data }) .done(function (msg){ console.log(msg); });*/ var xhr = new XMLHttpRequest(); // var url = "/mytest?"+data; var url = "/mytest"; xhr.open("post",url,true); xhr.onreadystatechange = function (){ if (xhr.readyState == 4) { if (xhr.status == 200) { console.log(xhr.responseText); } } }; xhr.send("test=i am a test"); }); });
于是有了圖三,圖四,兩張圖分別是改動open方法中的第一個參數分別為get和post,由于post方法的數據是放在body上的從圖四中我們可以認為request payload 代表的就是body,而get方法在url沒有接數據的時候沒有query string paramters 也沒有request payload,那么如果我們將body與request payload等同的話,則可以認為get方法發送請求時報文并沒有發送body,另外從w3c收到關于body的介紹
4.3 Message Body The message-body (if any)of an HTTP message is used to carry the entity-body associated with the request or response. The message-body differs from the entity-body only when a transfer-coding has been applied, as indicated by the Transfer-Encoding header field (section 14.41).
注意到其中的if any便可知道,http請求其實是可以沒有body的,所以完全有理由相信get方法發送請求時甚至都不發送body。
綜上,我們可以知道,其實get和post都有其存在的必要信,雖然只有其中的一個我們依舊可以實現獲取資源,發送數據的最終目的,但是為了更好的利用網絡資源,區分出get和post方法時真的非常有必要的