本文從如下幾個方面走進 GET 與 POST 的區別:前端
GET 與 POST 是 HTTP 請求中最經常使用的兩種方法,GET 與 POST 的區別也是老生常談的問題了,信手拈來git
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 中。 |
上面是 w3school 給出的標準答案github
但你真的理解它嗎?在咱們學習了那麼多 HTTP 知識後,僅僅回答這些就夠了嗎?GET 與 POST 都是 HTTP 的請求方法,如何理解請求方法?本質區別又是什麼?web
下面讓咱們一步步走進 GET 與 POST 方法,以及二者的本質區別面試
HTTP (HyperText Transfer Protocol)是創建在 TCP 上的應用層協議,超文本傳輸協議。其中:算法
因此,HTTP 協議用更通俗易懂的話描述就是 一個在計算機世界裏專門在兩點之間傳輸文字、圖片、音頻、視頻等超文本數據的約定和規範跨域
雖然說 HTTP 協議是「傳輸協議」,但它不關心尋址、路由、數據完整性等傳輸細節,這些底層的具體傳輸工做是由 TCP/IP 協議負責,例如 IP 協議實現尋址和路由、TCP 協議實現可靠數據傳輸,另外還有 DNS 協議實現域名查找、SSL/TLS 協議實現安全通訊等瀏覽器
那 HTTP 協議主要幹嗎喃?緩存
HTTP 協議的核心部分就是它定義的傳輸報文的格式,例如報文的組成、解析規則等,以便於在 TCP/IP 上實現更多樣靈活的功能,如緩存控制、數據編碼、內容協議等安全
HTTP 報文分爲四部分:
注意:此報文中最後是一個空白行結束,沒有 body(GET 請求通常都沒有 body)
其中,請求方法就規定在起始行中:
客戶端發起 HTTP 請求,服務器響應客戶端請求,客戶端能夠對服務器端的資源進行操做,例如查詢、添加、刪除等,但具體執行哪一種操做喃?
這就是請求方法存在的意義,它規定了客戶端的某種操做指令,用來告訴服務器端我須要進行哪一種操做,常見的請求方法有:
GET 請求方法應該是 HTTP 全部請求方法中最開始出現的了,它表示從服務器獲取資源
POST 請求方法是 HTTP 全部協議中除 GET 以外最常使用的請求方法了,它表示向指定的服務器資源提交數據,提交數據存放在 HTTP 報文中的 body 中,一般致使狀態或服務器上的反作用的更改
綜上所述,總結一下,GET 與 POST 的本質區別有兩點:
在 HTTP 協議裏,所謂的「安全」是指請求方法不會對服務器上的資源進行修改,「破壞」服務器上的資源
按照這種定義,GET 請求方法是安全的,它對服務器資源執行的僅僅是隻讀操做,也是冪等的
冪等指屢次執行相同的操做,結果也都是相同的,即屢次「冪」後結果「相等」
POST 請求方法是不安全的,它會修改服務器上的資源,在 RFC 裏的語義,POST 是指「新增或提交數據」,屢次提交數據會建立多個資源,因此不是冪等的
總結:
對於傳輸來講,GET 和 POST 報文在傳輸上都是不安全的,由於 HTTP 在網絡上是明文傳輸的,想要安全傳輸就得加密,也就是 HTTPS
這個就神奇了,在部分文章中提到,POST 請求方法會將 header 和 body 分開發送,先發送 header,服務端返回 100 狀態碼再發送 body 🤔️🤔️🤔️
HTTP 協議中沒有明確說明 POST 會產生兩個 TCP 數據包,並且實際測試(Chrome、Firefox)發現,header 和 body 不會分開發送。
但爲何有些做者會這樣寫喃?我查找了相關資料,終於發現,真有這種狀況,原文在這裏:
In search of performance - how we shaved 200ms off every POST request
主要內容是做者發現 POST 比 GET 多 200ms,而後深刻研究,發現 ruby 的 net::HTTP 庫,會將一個 http 請求拆分,先發送 header 部分。另外,因爲沒有設置 TCP_NODELY ,因此第一個包以後要等待 ack ,才發下一個包,致使了一個請求有 200ms 的延遲。
另外,關於 HTTP 100 Continue:
100 Continue的目的是對HTTP客戶端應用程序有一個實體的主體部分要發送服務器,但但願在發送以前查看一下服務器是否會接受這個實體這種狀況進行優化
----《HTTP權威指南》
客戶端:
若是客戶端在向服務器發送一個實體,並願意在發送實體以前等待100 Continue響應,那麼客戶端就要發送一個攜帶了值爲100 Continue的Expect請求首部。若是客戶端沒有發送實體,就不該該發送100 Continue Expect首部,由於這樣會使服務器誤覺得客戶端要發送一個實體
服務器端:
若是服務器收到一條帶有值爲100 Continue的Expect首部的請求,它會用100 Continue響應或一條錯誤碼來進行響應。服務器永遠也不該該向沒有發送100 Continue指望的客戶端發送100 Continue狀態碼。
若是服務器在有機會發送100 Continue響應以前就收到了部分(或者所有)的實體,說明服務器已經打算繼續發送數據了,這樣服務器就不須要發送這個狀態碼了,可是服務器完成請求以後,仍是應該爲請求發送一個最終狀態碼
也就是說,沒收到客戶端的 100 Continue 就不會有響應
所以,大多數框架都是儘可能在一個 TCP 包裏面把 HTTP 請求發出去的,可是也確實存在先發 HTTP 頭,而後發 body 的框架。可是具體發多少個TCP包,這個 不是 HTTP 協議的事情是操做系統 TCP 協議棧與代碼的問題,跟 HTTP 不要緊