1. 面試官:post為什么會(huì)發(fā)送兩次請(qǐng)求?

        共 3426字,需瀏覽 7分鐘

         ·

        2024-08-05 08:45

        之前有人跟我們說(shuō),出去面試的時(shí)候,有時(shí)候會(huì)遇到一些讓人頭疼的問(wèn)題,比如有一次去字節(jié)面試,面試官就問(wèn)了一個(gè)讓他很奇怪的問(wèn)題:“為啥POST請(qǐng)求有時(shí)候會(huì)發(fā)送兩次呢?”這個(gè)問(wèn)題聽(tīng)起來(lái)挺玄乎的,但其實(shí)用大白話來(lái)說(shuō),原因還挺簡(jiǎn)單的。咱們這就來(lái)聊聊這個(gè)事兒。
        首先,得明白啥是POST請(qǐng)求。POST請(qǐng)求就是咱們?cè)诰W(wǎng)上干點(diǎn)啥事兒,比如提交個(gè)表單、上傳個(gè)文件啥的,得跟服務(wù)器說(shuō):“嘿,我這兒有點(diǎn)東西,你給我處理一下。”這時(shí)候,瀏覽器就會(huì)發(fā)個(gè)POST請(qǐng)求給服務(wù)器。
        那么,為啥有時(shí)候會(huì)發(fā)兩次呢?這其實(shí)跟瀏覽器的“預(yù)檢”機(jī)制有關(guān)系。簡(jiǎn)單來(lái)說(shuō),就是瀏覽器在正式發(fā)請(qǐng)求之前,會(huì)先問(wèn)問(wèn)服務(wù)器:“嘿,我要發(fā)請(qǐng)求了,你準(zhǔn)備好了嗎?能接收嗎?”這個(gè)過(guò)程就叫做“預(yù)檢請(qǐng)求”,也叫OPTIONS請(qǐng)求。
        為啥要有這個(gè)預(yù)檢呢?因?yàn)橛袝r(shí)候咱們發(fā)的請(qǐng)求可能比較復(fù)雜,比如請(qǐng)求頭里面帶了點(diǎn)特殊的東西,或者請(qǐng)求方法是PUT、DELETE這種不常用的。這時(shí)候,瀏覽器就會(huì)有點(diǎn)擔(dān)心,怕服務(wù)器不理解或者不接受這個(gè)請(qǐng)求,所以就先發(fā)個(gè)簡(jiǎn)單的OPTIONS請(qǐng)求去問(wèn)問(wèn)。
        如果服務(wù)器說(shuō):“沒(méi)問(wèn)題,你來(lái)吧!”那瀏覽器就會(huì)再發(fā)一次正式的POST請(qǐng)求。所以,咱們就看到了兩次請(qǐng)求:一次是預(yù)檢的OPTIONS請(qǐng)求,一次是正式的POST請(qǐng)求。
        那么,舉個(gè)實(shí)際的例子來(lái)說(shuō)明一下。假設(shè)你正在開(kāi)發(fā)一個(gè)網(wǎng)頁(yè)應(yīng)用,其中有一個(gè)功能是讓用戶能夠上傳圖片。當(dāng)用戶選擇了一張圖片并點(diǎn)擊上傳按鈕時(shí),瀏覽器就會(huì)發(fā)送一個(gè)POST請(qǐng)求到服務(wù)器,以便將圖片上傳到服務(wù)器上。
        但是,如果這個(gè)請(qǐng)求中包含了一些特殊的請(qǐng)求頭,比如自定義的X-Requested-With頭,或者請(qǐng)求的內(nèi)容類型(Content-Type)不是常見(jiàn)的application/x-www-form-urlencoded、multipart/form-datatext/plain,那么瀏覽器就會(huì)先發(fā)送一個(gè)OPTIONS請(qǐng)求進(jìn)行預(yù)檢。
        這個(gè)OPTIONS請(qǐng)求會(huì)詢問(wèn)服務(wù)器是否接受這種類型的請(qǐng)求。如果服務(wù)器響應(yīng)說(shuō)可以接受,那么瀏覽器才會(huì)繼續(xù)發(fā)送正式的POST請(qǐng)求,將圖片上傳到服務(wù)器上。
        預(yù)檢請(qǐng)求和正式請(qǐng)求之間有一些明顯的區(qū)別。首先,它們的目的不同。預(yù)檢請(qǐng)求的目的是詢問(wèn)服務(wù)器是否接受某種類型的請(qǐng)求,而正式請(qǐng)求則是實(shí)際執(zhí)行某種操作,比如上傳文件、提交表單等。其次,它們的請(qǐng)求方法不同。預(yù)檢請(qǐng)求總是使用OPTIONS方法,而正式請(qǐng)求則可以使用GET、POST、PUT、DELETE等方法。最后,它們的請(qǐng)求頭和請(qǐng)求體也可能不同。預(yù)檢請(qǐng)求通常只包含一些基本的請(qǐng)求頭,而正式請(qǐng)求則可能包含更多的請(qǐng)求頭和請(qǐng)求體數(shù)據(jù)。
        所以,先總結(jié)一下,POST請(qǐng)求有時(shí)候會(huì)發(fā)送兩次,是因?yàn)闉g覽器為了保險(xiǎn)起見(jiàn),先發(fā)個(gè)預(yù)檢請(qǐng)求去問(wèn)問(wèn)服務(wù)器:“我能發(fā)這個(gè)請(qǐng)求嗎?”得到允許后,再發(fā)正式的請(qǐng)求。這樣,就能確保咱們的請(qǐng)求能夠順利到達(dá)服務(wù)器,并得到正確的處理了。
        好了,現(xiàn)在大家明白了吧,以后面試遇到這個(gè)問(wèn)題就可以很好的回答清楚了,說(shuō)白了不是發(fā)送兩次post請(qǐng)求,而是在一些特殊的情況下,如果post請(qǐng)求要帶一些特殊的請(qǐng)求頭,平時(shí)不太常見(jiàn),瀏覽器就會(huì)發(fā)擔(dān)心服務(wù)端沒(méi)法接收和處理,那如果服務(wù)端沒(méi)法處理,自己何必還發(fā)送post請(qǐng)求攜帶大量的表單數(shù)據(jù)、文件數(shù)據(jù)、圖片數(shù)據(jù)過(guò)去呢?這不是吃飽了沒(méi)事干么,對(duì)吧!
        所以此時(shí)才會(huì)先發(fā)個(gè)options預(yù)檢請(qǐng)求過(guò)去,帶一些請(qǐng)求頭,問(wèn)一下服務(wù)端后面能不能處理正式的請(qǐng)求。另外的話,對(duì)于發(fā)options預(yù)檢請(qǐng)求的情況還有一種比較特殊的,就是同源策略下的跨域訪問(wèn),這個(gè)也是有可能會(huì)提前發(fā)options預(yù)檢請(qǐng)求的。
        瀏覽器的同源策略,簡(jiǎn)單來(lái)說(shuō),就是瀏覽器為了安全起見(jiàn),設(shè)置的一個(gè)規(guī)矩。這個(gè)規(guī)矩規(guī)定,來(lái)自不同源的網(wǎng)頁(yè)之間不能直接進(jìn)行交互。這里的“源”指的是協(xié)議(比如http或https)、域名(比如www.example.com)和端口號(hào)(比如80或443)這三者的組合。只要這三者中有任何一個(gè)不同,就認(rèn)為是不同的源。
        那不同的源肯定不能互相瞎請(qǐng)求啊,比如說(shuō)瀏覽器請(qǐng)求服務(wù)器A返回了一個(gè)網(wǎng)頁(yè),結(jié)果這個(gè)服務(wù)器A跑的A系統(tǒng)的網(wǎng)頁(yè)里,有一個(gè)請(qǐng)求要去請(qǐng)求服務(wù)器B上部署的B系統(tǒng),那這種就很奇怪了,對(duì)瀏覽器來(lái)說(shuō)你們是兩個(gè)服務(wù)器,也就是兩個(gè)不同的系統(tǒng),干什么要互相瞎訪問(wèn),有沒(méi)有可能A系統(tǒng)是一個(gè)涉灰系統(tǒng)在搞破壞,盜取數(shù)據(jù),對(duì)不對(duì)?
        舉個(gè)日常的例子,就像你有兩個(gè)家,一個(gè)在北京,一個(gè)在上海。雖然都是你的家,但因?yàn)榈乩砦恢貌煌ň拖駞f(xié)議、域名、端口號(hào)不同),所以你不能直接從北京的家跑到上海的家去拿東西,除非你走特殊通道(就像跨域資源共享CORS)。
        那CORS的話,全稱是跨域資源共享(Cross-Origin Resource Sharing),是瀏覽器和服務(wù)器之間的一種約定,用來(lái)解決跨域請(qǐng)求的問(wèn)題。簡(jiǎn)單來(lái)說(shuō),CORS就是一種機(jī)制,讓服務(wù)器告訴瀏覽器:“嘿,這個(gè)網(wǎng)頁(yè)雖然來(lái)自不同的源,但它是安全的,你可以讓它訪問(wèn)我的資源。”
        就是說(shuō)服務(wù)器A的網(wǎng)頁(yè)里的JS代碼去請(qǐng)求服務(wù)器B了,那就是跨域了,那跨域發(fā)起的請(qǐng)求就是CORS請(qǐng)求了。
        那瀏覽器發(fā)跨域請(qǐng)求的時(shí)候,會(huì)不回發(fā)options預(yù)檢請(qǐng)求呢?其實(shí)也是會(huì)的,因?yàn)楫?dāng)瀏覽器發(fā)起跨域請(qǐng)求時(shí),并不是所有的請(qǐng)求都會(huì)直接發(fā)送。有時(shí)候,瀏覽器也是會(huì)先發(fā)出一個(gè)OPTIONS請(qǐng)求,這個(gè)請(qǐng)求就像是瀏覽器在問(wèn)服務(wù)器:“嘿,我這兒有一個(gè)網(wǎng)頁(yè)想發(fā)個(gè)請(qǐng)求到你的地盤(pán),但是網(wǎng)頁(yè)和你的話,咱倆不是同一個(gè)源的,你得先告訴我,你同不同意?”這個(gè)過(guò)程就叫做跨域請(qǐng)求之前的預(yù)檢請(qǐng)求。
        那么,跨域請(qǐng)求的時(shí)候,什么情況下會(huì)發(fā)出OPTIONS預(yù)檢請(qǐng)求呢?主要有以下幾種情況:
        1、請(qǐng)求方法不是GET、HEAD、POST:因?yàn)镚ET、HEAD、POST這三種方法被認(rèn)為是“簡(jiǎn)單”的,通常不會(huì)對(duì)服務(wù)器造成太大影響,所以瀏覽器會(huì)直接發(fā)送請(qǐng)求。但如果是PUT、DELETE等方法,瀏覽器就會(huì)先發(fā)個(gè)OPTIONS請(qǐng)求問(wèn)問(wèn),就怕有人要搞破壞。
        對(duì)于GET、HEAD、POST這種簡(jiǎn)單請(qǐng)求,瀏覽器是沒(méi)有預(yù)檢請(qǐng)求的,他會(huì)直接發(fā)送請(qǐng)求到服務(wù)器,并在請(qǐng)求頭中包含一個(gè)Origin字段,表明這個(gè)請(qǐng)求的來(lái)源。服務(wù)器收到請(qǐng)求后,會(huì)根據(jù)請(qǐng)求頭中的Origin字段來(lái)決定是否允許這個(gè)跨域請(qǐng)求。如果允許,服務(wù)器會(huì)在響應(yīng)頭中包含Access-Control-Allow-Origin字段,并返回相應(yīng)的資源。
        但是大部分情況下,很多后端系統(tǒng)如果用的是MVC框架的話,都會(huì)默認(rèn)禁止CORS跨域請(qǐng)求,所以這個(gè)時(shí)候如果你發(fā)現(xiàn)后端系統(tǒng)異常了,配置一下MVC框架,打開(kāi)CORS跨域請(qǐng)求支持就可以了,那就可以處理跨域請(qǐng)求了。
        2、請(qǐng)求頭包含了自定義字段:比如你在請(qǐng)求頭里加了個(gè)X-Token,瀏覽器就會(huì)覺(jué)得:“咦,這個(gè)請(qǐng)求頭看起來(lái)不簡(jiǎn)單,我得先問(wèn)問(wèn)服務(wù)器同不同意?!?/span>
        3、Content-Type不是常見(jiàn)的三種類型:常見(jiàn)的Content-Type有application/x-www-form-urlencodedmultipart/form-datatext/plain。如果你用了其他類型,比如application/json,瀏覽器也會(huì)先發(fā)個(gè)OPTIONS請(qǐng)求。
        再總結(jié)一下,當(dāng)瀏覽器覺(jué)得一個(gè)跨域請(qǐng)求“不簡(jiǎn)單”時(shí),就會(huì)先發(fā)個(gè)OPTIONS請(qǐng)求去預(yù)檢一下,看看服務(wù)器同不同意。如果服務(wù)器同意了,瀏覽器才會(huì)繼續(xù)發(fā)送正式的請(qǐng)求。這就像你去別人家做客,如果不是很熟,你可能會(huì)先打個(gè)電話問(wèn)問(wèn)對(duì)方方不方便,得到同意后再去。
        好了,今天咱們從一個(gè)面試題問(wèn)post為什么發(fā)兩次請(qǐng)求開(kāi)始引入,用大白話重點(diǎn)聊了聊瀏覽器的options預(yù)檢請(qǐng)求問(wèn)題,并且舉了一些例子,尤其是講了一些同源策略、跨域請(qǐng)求、預(yù)檢請(qǐng)求之間的關(guān)系,相信大家也學(xué)到了不少東西,以后面試遇到一定要加油!

        瀏覽 157
        1點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        1點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 性色国产成人久久久精品 | 国产成人毛片无码视频不卡 | 色姑娘综合网 | 在线观看黄色小视频 | 男人插男人视频 |