get 和 post 是HTTP協議的兩種常用的請求方法,既然常用,那么就會經常有人問它們到底有什么區別呢?
對此總結出來以下五點:
- get 是不安全的,因為數據被放在URL里面傳輸,post 數據是放在請求體里面的。
- get 傳的數據量較小,主要是因為受URL長度限制,post 傳送的數據量一般不受限制。
- get 只能使用ascll編碼,post 沒有限制。
- get 請求是可緩存的,后退不刷新;post 請求不緩存,后退重新請求。
- get 是一次tcp連接,post一般是兩次。
根據HTTP規范,get 是用來獲取資源的,請求訪問已被 URL 識別的資源。post 向指定資源提交數據進行處理請求,可能會導致新的資源的建立和/或已有資源的修改。雖然用 get 方法也可以傳輸實體的主體,但一般不用 get 方法進行傳輸,而是用 post 方法。
本來我是想總結一下兩種方法的區別,但是無意間看到一篇博客里面提到前兩條區別都是錯誤的。里面還詳細給出了錯誤的原因,覺得說的很有道理,因此在下面用前兩條轉載一下此篇博客中提到的解釋。
一、GET和POST與數據如何傳遞沒有關系
GET和POST是由HTTP協議定義的。在HTTP協議中,Method和Data(URL, Body, Header)是正交的兩個概念,也就是說,使用哪個Method與應用層的數據如何傳輸是沒有相互關系的。
HTTP沒有要求,如果Method是POST數據就要放在BODY中。也沒有要求,如果Method是GET,數據(參數)就一定要放在URL中而不能放在BODY中。
那么,網上流傳甚廣的這個說法是從何而來的呢?我在HTML標准中,找到了相似的描述。這和網上流傳的說法一致。但是這只是HTML標准對HTTP協議的用法的約定。怎么能當成GET和POST的區別呢?
而且,現代的Web Server都是支持GET中包含BODY這樣的請求。雖然這種請求不可能從瀏覽器發出,但是現在的Web Server又不是只給瀏覽器用,已經完全地超出了HTML服務器的范疇了。
二、HTTP協議對GET和POST都沒有對長度的限制
HTTP協議明確地指出了,HTTP頭和Body都沒有長度的要求。而對於URL長度上的限制,有兩方面的原因造成:
1. 瀏覽器。據說早期的瀏覽器會對URL長度做限制。據說IE對URL長度會限制在2048個字符內(流傳很廣,而且無數同事都表示認同)。但我自己試了一下,我構造了90K的URL通過IE9訪問live.com,是正常的。網上的東西,哪怕是Wikipedia上的,也不能信。
2. 服務器。URL長了,對服務器處理也是一種負擔。原本一個會話就沒有多少數據,現在如果有人惡意地構造幾個幾M大小的URL,並不停地訪問你的服務器。服務器的最大並發數顯然會下降。另一種攻擊方式是,把告訴服務器Content-Length是一個很大的數,然后只給服務器發一點兒數據,嘿嘿,服務器你就傻等着去吧。哪怕你有超時設置,這種故意的次次訪問超時也能讓服務器吃不了兜着走。有鑒於此,多數服務器出於安全啦、穩定啦方面的考慮,會給URL長度加限制。但是這個限制是針對所有HTTP請求的,與GET、POST沒有關系。
三、關於區別五的解釋
對於get方式的請求,瀏覽器會把http header和data一並發送出去,服務器響應200(返回數據);
而對於post,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
也就是說,get只需要汽車跑一趟就把貨送到了,而post得跑兩趟,第一趟,先去和服務器打個招呼“嗨,我等下要送一批貨來,你們打開門迎接我”,然后再回頭把貨送過去。
因為post需要兩步,時間上消耗的要多一點,看起來get比post更有效。
其實據研究,在網絡環境好的情況下,發一次包的時間和發兩次包的時間差別基本可以無視。而在網絡環境差的情況下,兩次包的TCP在驗證數據包完整性上,有非常大的優點。
並不是所有瀏覽器都會在post中發送兩次包,Firefox就只發送一次。