您好,登錄后才能下訂單哦!
在GET請求中使用body的實例分析,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
故事還得從一個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:
[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都直接去掉了,要求更加寬松:
[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”。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。