報文
常見 GET 的報文如下
GET /index.html?name=everlose&age=28 HTTP/1.1
Host: localhost
...省略其他 request header
常見 POST 報文如下
POST /index.html HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
...省略其他 request header
name=everlose&age=28
從報文中可得知兩者的形式,區別也只在於 HTTP method。大家不要被常見形式誤解了,兩種請求方法都可以在路徑哪裏寫上 ?
後的參數,並且兩種方法都可以寫上 HTTP Body。
換言之,GET 和 POST 方法沒有實質區別,只是瀏覽器或者說其他的端對這兩者的表現給出了一些區別。
瀏覽器的表現形式
摘錄自 w3school HTTP 方法:GET 對比 POST
特性 | GET | POST |
---|---|---|
後退按鈕/刷新 | 無害 | 數據會被重新提交(瀏覽器應該告知用戶數據會被重新提交)。 |
書籤 | 可收藏爲書籤 | 不可收藏爲書籤 |
緩存 | 能被緩存 | 不能緩存 |
編碼類型 | application/x-www-form-urlencoded | application/x-www-form-urlencoded 或 multipart/form-data。爲二進制數據使用多重編碼。 |
歷史 | 參數保留在瀏覽器歷史中。 | 參數不會保存在瀏覽器歷史中。 |
對數據長度的限制 | 是的。當發送數據時,GET 方法向 URL 添加數據;URL 的長度是受限制的(URL 的最大長度是 2048 個字符)。 | 無限制。 |
對數據類型的限制 | 只允許 ASCII 字符。 | 沒有限制。也允許二進制數據。 |
安全性 | 與 POST 相比,GET 的安全性較差,因爲所發送的數據是 URL 的一部分。在發送密碼或其他敏感信息時絕不要使用 GET ! | POST 比 GET 更安全,因爲參數不會被保存在瀏覽器歷史或 web 服務器日誌中。 |
可見性 | 數據在 URL 中對所有人都是可見的。 | 數據不會顯示在 URL 中。 |
總之瀏覽器遵照 HTTP 標準規定,給兩種方法加以區別:
- GET 用於獲取信息,是無副作用的,是冪等的,且可緩存
- POST 用於修改服務器上的數據,有副作用,非冪等,不可緩存
那麼最本質的區別是什麼
有文章 99%的人都理解錯了HTTP中GET與POST的區別 提到是
GET產生一個TCP數據包;POST產生兩個TCP數據包。
並且說所有瀏覽器都會在 POST 中發送兩次包,Firefox就只發送一次。
那麼本人在真實 wireshark 抓包得到的 chrome 瀏覽器,它的確 POST 只發了一個包
查閱文章http post請求發兩個tcp包後續得知在 ruby 做客戶端發起 POST 請求時,會發送兩個數據包。故而說:
大多數框架都是儘量在一個 TCP 包裏面把 HTTP 請求發出去的,但是也確實存在先發 HTTP 頭,然後發 Body 的框架。但是具體發多少個 TCP 包,這個是代碼的問題,是 TCP 協議棧的問題,跟 HTTP 沒關係。
回答問題,最本質的區別,仍舊沒有。
說到這裏大概大家會有個疑惑,似乎明明能看到發 POST 請求,跨域的時候能在控制檯看到兩個請求,第一個是 Options,但這其實是另一個話題,參見我的另外一篇 HTTP Options 跨域時發送兩個請求是怎麼回事?
參考
Fundebug-都 2019 年了,還問 GET 和 POST 的區別
WebTechGarden-99%的人都理解錯了HTTP中GET與POST的區別