故事還得從一個bug提及。今天有人問我,爲何發到後端的請求400了,我說確定是參數不對,你去檢查檢查GET、POST之類的方法寫沒寫對,要麼就是字段沒對上,無非是這幾個問題。而後他說檢查過了,沒問題啊;我不太相信,可是看了看前端發送的請求,好像確實沒啥問題:前端
我說既然這樣,那確定是後端寫錯了,但後端說他已經用postman測過了,確定沒問題。這就頗有意思了。因而我要來了後端的代碼:
不出所料,後端把GET請求裏的參數當成body的內容了,把@RequestBody改爲@RequestParam應該就沒問題了;改完以後果真好了。後端
這原本是一個很簡單的問題,沒什麼可說的,可是他們接着問我,爲何GET請求裏不能用body?我尋思着平時也沒什麼人在GET請求里加body吧,並且一直以來都據說這麼用很差。可是爲何很差呢?因此我就查了一些資料,最後乾脆又去RFC翻了翻。看到官方是這麼說的:瀏覽器
[RFC7231] A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.緩存
意思是你往GET請求里加body是不符合規範的,不保證全部的實現都支持(主要是之前的實現,由於之前曾經有相應的規定),要是出了啥問題別怪我沒提醒你。並且聽說老版本的postman是不支持在GET請求里加body的,也是最近才加上的支持;因此要放在之前也就沒這些問題了,之前的postman根本發不了帶body的GET請求。安全
可是這一條並非強制規定。我看不少人都強調一點,GET請求不該攜帶請求體,服務器應忽略(或者說丟棄)GET請求的請求體。這一條的確是有依據的,來源以下:服務器
[RFC2616] A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.網絡
固然,官方也只是說SHOULD,沒有像前文同樣措辭嚴厲地強調相似HEAD這種的請求MUST NOT have a message body:post
[RFC2616] A message-body MUST NOT be included in a request if the specification of the request method does not allow sending an entity-body in requests.學習
可是很惋惜的是,RFC2616已通過時了。如今的說法變成了這樣,連SHOULD都直接去掉了,要求更加寬鬆:.net
[RFC7230] Request message framing is independent of method semantics, even if the method does not define any use for a message body.
難道是由於錯的人多了,錯的也變成了對的?不過即便是這樣,也並非在GET請求里加上body的理由。
這個問題算是解決了。可是我看到網上各路大神說到GET加body的時候,還提到一個,就是往GET里加body會致使緩存機制失效。「GET 被設計來用 URI 來識別資源,若是讓它的請求體中攜帶數據,那麼一般的緩存服務便失效了,URI 不能做爲緩存的 Key。」我一開始覺得是在服務器上配置的緩存,好比Nginx的cache之類的機制,後來發現好像並不是如此。這個緩存,大概是指那種預加載和後存儲,會涉及到一個網絡請求的「安全性」。若是不安全,顯然是不能緩存的。
那麼,GET和POST的區別和應用?這問題挺複雜。簡而言之,就是「安全」和「不安全」的區別。什麼是安全?不用承擔責任。什麼是不安全?可能須要承擔責任。舉個例子,點擊某個連接以贊成某個協議,這個請求明顯就是不安全的,由於須要承擔責任。若是採用GET,就違反了GET應該用於安全請求的規範。由於瀏覽器可能在你不知情的狀況下預加載這個頁面(由於是「安全」的GET請求),這樣至關於你在不知情的狀況下贊成了某個協議,這顯然是咱們不但願看到的。在契約式的設計裏,違反契約的行爲是會帶來嚴重的後果的。瀏覽器按照契約預加載了安全的GET請求,但這自己是不安全的,帶來的後果天然要由打破契約的人承擔(將這個請求設計成GET的人出來捱打)。
之因此強調「安全」,而不是按照常規的說法強調反作用,由於有反作用的請求不表明不安全;舉例來講,服務器有一個顯示訪問人數的功能,這個功能就能夠用GET來作。雖然每次訪問都會發送改變服務器狀態(計數器)的請求,但用戶不會由於這個請求承擔責任,這個請求是安全的。至於什麼GET請求的URL有長度限制(後來事實證實其實沒有),什麼GET請求的URL裏不能有中文(或者說非ASCII吧),都只是實現上的區別;從最初的設計上來講區別並不在這裏。
固然,這些都是純粹的理論層面的東西。若是遵照RESTful的規範,採用語義化的GET/POST請求,天然也就不會有這些問題了。由於一般來講,查詢是安全的;這也是GET的主要做用。
提及來也挺有意思的,學習了這麼久,常常提起RFC,也沒搞清楚RFC到底是個啥玩意,此次就一併查了。雖然我總以爲這是受到6f名詞解釋的影響……原來是叫「Request For Comments」。
參考文章(不分前後):
再也不以訛傳訛,GET和POST的真正區別 HTTP GET with request body 誰說 HTTP GET 就不能經過 Body 來發送數據呢? URIs, Addressability, and the use of HTTP GET and POST 此外,'URIs, Addressability, and the use of HTTP GET and POST’這篇文章我翻譯成了中文,歡迎各位閱讀並指正;翻譯水平實在有限,只能說「盡最大努力交付」。 --------------------- 做者:元無意 來源:CSDN 原文:https://blog.csdn.net/HermitSun/article/details/89889743 版權聲明:本文爲博主原創文章,轉載請附上博文連接!