get和post是http請求的兩種基本方法,最直觀的區別是get把參數包含在url中,post通過request body傳遞參數
-
get在瀏覽器回退時是無害的,而post會再次提交請求。
-
get產生的url地址可以被bookmark,而post不可以
-
get請求會被瀏覽器主動catche,而post不會,除非手動設置。
-
get請求只能進行url編碼,而post支持多種編碼方式
-
get請求參數會被完整保留在瀏覽器歷史記錄里,而post中的參數不會被保留
-
get請求在url中傳送的參數是有長度限制的,而post中的參數不會被保留
-
對參數的數據類型,get只接受按時ASCLL字符,而post沒有限制
-
get比post跟那個不安全,因為參數直接暴露在url上,所以不能用來傳遞敏感信息
-
get參數通過url傳遞,post放在request body中
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標簽(設置method為post),並把貨物放在車廂里,當然,你也可以在get的時候往車廂里偷偷藏點貨,但是這很不光彩;也可以在post的時候在車頂上放一些數據,讓人覺得傻乎乎的。http只是個行為准則,而TCP才是get和post怎么實現的基本。
總結一下,我們的最終目的是傳遞數據,需要傳遞的載體也就是車(TCP),http告訴你怎么把數據放在載體上才能允許你能傳遞成功,而get和post就是http制定的放數據的規則,也就是get只能把數據放在外面,也就是url里,而post只能放在里面,也就是request body。雖然他們也可以附帶,但是不一定會被就服務器接收,因為這就要考慮瀏覽器和服務器的問題了,接着往下看:
不同的瀏覽器(發起http請求)和服務器(接受http請求)就是不同的運輸公司。雖然理論上,你可以在車頂上無限的堆貨物(url中無限加參數)。但是運輸公司可不傻,裝貨和卸貨也是有很大的成本的,他們會限制單次運輸量來控制風險,數據量太大對瀏覽器和服務器都是很大的負擔。業界不成文規定大多數的瀏覽器通常都會限制url長度在2k個字節,而大多數服務器最多處理64k大小的url。超過的部分,就不處理了,如果用get服務,在request body偷偷藏了數據,不同服務器的處理方式也是不同的,有些服務器會幫你卸貨,讀出數據,有些服務器直接忽略,所以,雖然get可以帶request body,也不能保證一定能被接收到。
事實上,get產生一個tcp數據包,而post會產生兩個tcp數據包。對於get方式請求,瀏覽器會把http header和data一並發送出去,服務器響應200(返回數據);而對於post,瀏覽器會先發送header,服務器響應100 continue,瀏覽器在發送data,服務器響應200(返回數據)
也就是說,get只需要汽車跑一趟就把貨送到了,而post得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然后再回頭把貨送過去。
因為post需要兩步,時間上消耗的要多一點,看起來get比post更有效。因此Yahoo團隊有推薦用get替換post來優化網站性能。但這是一個坑!跳入需謹慎。為什么?
-
get與post都有自己的語義,不能隨便混用。
-
據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的TCP在驗證數據包完整性上,有非常大的優點。
-
並不是所有瀏覽器都會在post中發送兩次包,Firefox就只發送一次。
