GET和POST的差別
超文本傳輸協定
HTTP
的設計目的是保證用戶端與服務端之間的通信,
HTTP
協定的工作方式是用戶端與服務端之間的請求響應,在用戶端與服務端進行請求響應時最常用的兩種方法就是
GET
與
POST
。
差別
-
是安全的、幂等的,而GET
是 不安全的、不幂等的。POST
-
在浏覽器回退或者重新整理時是無害的,而GET
會再次送出資料請求。POST
-
産生的GET
位址可以作為書簽儲存,而URL
不行。POST
-
請求會被浏覽器主動GET
,而cache
不會主動緩存。POST
-
請求隻能進行GET
編碼,而url
支援多種編碼方式。POST
-
請求參數會被完整保留在浏覽器曆史記錄裡,而GET
中的參數不會被保留。POST
-
請求在GET
中傳送的參數長度受URL
長度限制,而URL
的大小取決于後端配置。POST
-
參數隻接受GET
字元的資料類型,而ASCII
沒有限制,可以傳輸二進制資料。POST
-
比GET
更不安全,因為參數直接暴露在POST
上,是以不适合傳遞敏感資訊。URL
-
參數通過GET
傳遞,直接可見,URL
的參數放在POST
中,不直接可見。Request body
詳解
上述的差別都是
GET
POST
在浏覽器中的具體實作上的差別,例如現在廣泛使用的
Promise
就是各種對于
Promise/A+
的規範
promisesaplus.com
的實作,在
HTTP/1.1
的規範的征求意見稿
RFC
中提到了語義這個詞語,語義定義了一個類型的請求應該具有什麼樣的,例如
GET
的語義就應該是擷取資源,
POST
的語義就是修改資源,如果在符合文法的前提下實作違背語義的行為也是可以做到的,例如使用
GET
修改資源或者使用
POST
擷取資源,甚至使用
GET
發送
body
(這需要服務端能夠配合解析),這是合法的請求但是這是不符合語義的請求,而且很有可能會帶來一些副作用,是以在本質上
GET
POST
的差別是其語義的差別,甚至可以了解為
GET
POST
并沒有什麼差別,隻要用戶端與服務端能夠配合發送與接收即可,一個敢發一個敢收就可以了,而上文所述的差別主要是在浏覽器中具體實作上的差別。
關于安全性與幂等性,安全性是指通路接口時不會對服務端資源狀态發生改變,幂等性是指對于同一接口的
URI
多次通路時,得到的資源狀态是相同的。
-
: 安全的,幂等的,用于讀取資源。GET
-
: 不安全的,不幂等的,用于服務端自動産生的執行個體号建立資源,更新部分資源。POST
-
: 不安全的,幂等的,用于用戶端的執行個體号建立資源,更新資源。PUT
-
: 不安全的,幂等的,用于用戶端執行個體号删除資源。DELETE
在浏覽器點選後退操作時,如果将要傳回的頁面是
GET
請求的,那麼将會安全的進行回退,如果将要傳回的頁面是
POST
請求的,例如使用
<form>
的
method
為
POST
去送出資料并跳轉頁面的話,浏覽器會發出一個是否再次送出表單的确認提示。
關于
GET
和
POST
送出的參數長度的限制問題,
GET
是通過
URL
送出資料,是以
GET
可送出的資料量就跟
URL
所能達到的最大長度有直接關系,實際上
HTTP
協定對
URL
長度是沒有限制的,但是在各種浏覽器中對于
URL
長度是有限制的,而且限制的長度是不同的,一般使用不超過
4K
,此外服務端也會對于
URL
有各自的限制,當然服務端可以接收的
URL
長度大小是可以配置的,同樣的,
HTTP
協定沒有對
POST
進行任何限制,
POST
送出的資料大小一般是受伺服器的主動配置來限定大小。
關于敏感資訊不要使用
GET
進行傳輸主要有兩個方面的考慮,首先使用
GET
傳輸敏感資訊會直接暴露在
URL
上,會直接可見,此外使用
GET
傳輸的參數會被直接儲存在浏覽器的曆史記錄中以及伺服器的日志中,當然
HTTP
協定本身就是一個明文傳輸的協定,無論是使用
GET
還是
POST
在中間人攻擊等情況下都是能夠拿到傳輸的資料的,如果需要避免中間人等攻擊需要使用
HTTPS
進行資料的加密傳輸。
GET
發送一個請求,
POST
發送兩個請求的問題,同樣這也是各種浏覽器對于
HTTP
協定的具體實作的案例,而不涉及
GET
POST
的本質差別,關于這個具體的實作在各種浏覽器上的表現并不相同,主要是浏覽器的網絡請求底層對于請求上優化的實作,例如需要使用
POST
傳輸一個大檔案,那麼浏覽器就有可能首先發送一個資料包并攜帶少量資料去檢測服務端是否能夠接收這個檔案,服務端在解析上傳的檔案時,總是會先完全解析全部的請求頭部,伺服器端總是希望能夠了解請求的控制資訊後,就能決定這個請求怎麼進一步處理,是拒絕還是接收,如果服務端允許接收這個檔案那麼用戶端會繼續發送資料進行上傳操作,如果服務端拒絕了就直接中斷上傳,這樣用以節省提高資料吞吐和降低帶寬的浪費。在本質上這和
HTTP
協定無關,這是浏覽器在具體實作上做的一些優化,例如在内部設定一次
POST
的資料超過
1KB
就先隻發請求頭,否則就一次性全發,用戶端甚至還可以做一些
Adaptive
的政策,統計發送成功率,如果成功率很高,就總是全部發等等。不同浏覽器可以有各自的不同的方案,不管怎樣做,優化目的總是在提高資料吞吐和降低帶寬浪費。無論浏覽器如何發送其總是符合
HTTP
協定的,是具體實作而不涉及
GET
POST
的本質差別。
每日一題
https://github.com/WindrunnerMax/EveryDay
參考
https://zhuanlan.zhihu.com/p/25028045
https://www.zhihu.com/question/28586791
https://mp.weixin.qq.com/s?__biz=MzI3NzIzMzg3Mw==&mid=100000054&idx=1&sn=71f6c214f3833d9ca20b9f7dcd9d33e4