您好,登錄后才能下訂單哦!
在GET請(qǐng)求中使用body的實(shí)例分析,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
故事還得從一個(gè)bug說(shuō)起。今天有人問(wèn)我,為什么發(fā)到后端的請(qǐng)求400了,我說(shuō)肯定是參數(shù)不對(duì),你去檢查檢查GET、POST之類的方法寫(xiě)沒(méi)寫(xiě)對(duì),要么就是字段沒(méi)對(duì)上,無(wú)非是這幾個(gè)問(wèn)題。然后他說(shuō)檢查過(guò)了,沒(méi)問(wèn)題??;我不太相信,但是看了看前端發(fā)送的請(qǐng)求,好像確實(shí)沒(méi)啥問(wèn)題:
我說(shuō)既然這樣,那肯定是后端寫(xiě)錯(cuò)了,但后端說(shuō)他已經(jīng)用postman測(cè)過(guò)了,肯定沒(méi)問(wèn)題。這就很有意思了。于是我要來(lái)了后端的代碼:
不出所料,后端把GET請(qǐng)求里的參數(shù)當(dāng)成body的內(nèi)容了,把@RequestBody改成@RequestParam應(yīng)該就沒(méi)問(wèn)題了;改完之后果然好了。
這本來(lái)是一個(gè)很簡(jiǎn)單的問(wèn)題,沒(méi)什么可說(shuō)的,但是他們接著問(wèn)我,為什么GET請(qǐng)求里不能用body?我尋思著平時(shí)也沒(méi)什么人在GET請(qǐng)求里加body吧,而且一直以來(lái)都聽(tīng)說(shuō)這么用不好。但是為什么不好呢?所以我就查了一些資料,最后干脆又去RFC翻了翻??吹焦俜绞沁@么說(shuō)的:
[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請(qǐng)求里加body是不符合規(guī)范的,不保證所有的實(shí)現(xiàn)都支持(主要是以前的實(shí)現(xiàn),因?yàn)橐郧霸?jīng)有相應(yīng)的規(guī)定),要是出了啥問(wèn)題別怪我沒(méi)提醒你。而且據(jù)說(shuō)老版本的postman是不支持在GET請(qǐng)求里加body的,也是最近才加上的支持;所以要放在以前也就沒(méi)這些問(wèn)題了,以前的postman根本發(fā)不了帶body的GET請(qǐng)求。
但是這一條并不是強(qiáng)制規(guī)定。我看很多人都強(qiáng)調(diào)一點(diǎn),GET請(qǐng)求不應(yīng)攜帶請(qǐng)求體,服務(wù)器應(yīng)忽略(或者說(shuō)丟棄)GET請(qǐng)求的請(qǐng)求體。這一條的確是有依據(jù)的,來(lái)源如下:
[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.
當(dāng)然,官方也只是說(shuō)SHOULD,沒(méi)有像前文一樣措辭嚴(yán)厲地強(qiáng)調(diào)類似HEAD這種的請(qǐng)求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已經(jīng)過(guò)時(shí)了?,F(xiàn)在的說(shuō)法變成了這樣,連SHOULD都直接去掉了,要求更加寬松:
[RFC7230] Request message framing is independent of method semantics, even if the method does not define any use for a message body.
難道是因?yàn)殄e(cuò)的人多了,錯(cuò)的也變成了對(duì)的?不過(guò)即使是這樣,也并不是在GET請(qǐng)求里加上body的理由。
這個(gè)問(wèn)題算是解決了。但是我看到網(wǎng)上各路大神說(shuō)到GET加body的時(shí)候,還提到一個(gè),就是往GET里加body會(huì)導(dǎo)致緩存機(jī)制失效?!癎ET 被設(shè)計(jì)來(lái)用 URI 來(lái)識(shí)別資源,如果讓它的請(qǐng)求體中攜帶數(shù)據(jù),那么通常的緩存服務(wù)便失效了,URI 不能作為緩存的 Key?!蔽乙婚_(kāi)始以為是在服務(wù)器上配置的緩存,比如Nginx的cache之類的機(jī)制,后來(lái)發(fā)現(xiàn)好像并非如此。這個(gè)緩存,大概是指那種預(yù)加載和后存儲(chǔ),會(huì)涉及到一個(gè)網(wǎng)絡(luò)請(qǐng)求的“安全性”。如果不安全,顯然是不能緩存的。
那么,GET和POST的區(qū)別和應(yīng)用?這問(wèn)題挺復(fù)雜。簡(jiǎn)而言之,就是“安全”和“不安全”的區(qū)別。什么是安全?不用承擔(dān)責(zé)任。什么是不安全?可能需要承擔(dān)責(zé)任。舉個(gè)例子,點(diǎn)擊某個(gè)鏈接以同意某個(gè)協(xié)議,這個(gè)請(qǐng)求明顯就是不安全的,因?yàn)樾枰袚?dān)責(zé)任。如果采用GET,就違反了GET應(yīng)該用于安全請(qǐng)求的規(guī)范。因?yàn)闉g覽器可能在你不知情的情況下預(yù)加載這個(gè)頁(yè)面(因?yàn)槭恰鞍踩钡腉ET請(qǐng)求),這樣相當(dāng)于你在不知情的情況下同意了某個(gè)協(xié)議,這顯然是我們不希望看到的。在契約式的設(shè)計(jì)里,違反契約的行為是會(huì)帶來(lái)嚴(yán)重的后果的。瀏覽器按照契約預(yù)加載了安全的GET請(qǐng)求,但這本身是不安全的,帶來(lái)的后果自然要由打破契約的人承擔(dān)(將這個(gè)請(qǐng)求設(shè)計(jì)成GET的人出來(lái)挨打)。
之所以強(qiáng)調(diào)“安全”,而不是按照常規(guī)的說(shuō)法強(qiáng)調(diào)副作用,因?yàn)橛懈弊饔玫恼?qǐng)求不代表不安全;舉例來(lái)說(shuō),服務(wù)器有一個(gè)顯示訪問(wèn)人數(shù)的功能,這個(gè)功能就可以用GET來(lái)做。雖然每次訪問(wèn)都會(huì)發(fā)送改變服務(wù)器狀態(tài)(計(jì)數(shù)器)的請(qǐng)求,但用戶不會(huì)因?yàn)檫@個(gè)請(qǐng)求承擔(dān)責(zé)任,這個(gè)請(qǐng)求是安全的。至于什么GET請(qǐng)求的URL有長(zhǎng)度限制(后來(lái)事實(shí)證明其實(shí)沒(méi)有),什么GET請(qǐng)求的URL里不能有中文(或者說(shuō)非ASCII吧),都只是實(shí)現(xiàn)上的區(qū)別;從最初的設(shè)計(jì)上來(lái)說(shuō)區(qū)別并不在這里。
當(dāng)然,這些都是純粹的理論層面的東西。如果遵守RESTful的規(guī)范,采用語(yǔ)義化的GET/POST請(qǐng)求,自然也就不會(huì)有這些問(wèn)題了。因?yàn)橥ǔ?lái)說(shuō),查詢是安全的;這也是GET的主要作用。
說(shuō)起來(lái)也挺有意思的,學(xué)習(xí)了這么久,經(jīng)常提起RFC,也沒(méi)搞清楚RFC究竟是個(gè)啥玩意,這次就一并查了。雖然我總覺(jué)得這是受到6f名詞解釋的影響……原來(lái)是叫“Request For Comments”。
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。