首先供上我的答案(也可能會(huì)打臉):
會(huì)烙丛≡髡耍跨域請(qǐng)求瀏覽器可以正常發(fā)送服務(wù)器也可以正常返回響應(yīng),只不過(guò)響應(yīng)被瀏覽器攔截了而已垫毙。
揭曉一下答案霹疫,請(qǐng)求有的時(shí)候會(huì)被執(zhí)行,有的時(shí)候不會(huì)執(zhí)行综芥。
那啥時(shí)候會(huì)執(zhí)行丽蝎,啥時(shí)候不會(huì)執(zhí)行呢?其實(shí)這個(gè)問(wèn)題主要要從以下幾個(gè)方面去考慮:
- 跨域究竟是誰(shuí)的策略毫痕?瀏覽器
- 在什么時(shí)機(jī)會(huì)攔截請(qǐng)求征峦?
- 究竟什么時(shí)候會(huì)發(fā)預(yù)檢請(qǐng)求迟几?非簡(jiǎn)單請(qǐng)求
- 如果有預(yù)檢,請(qǐng)求什么時(shí)候會(huì)被真正執(zhí)行栏笆?預(yù)檢請(qǐng)求返回允許跨域的相關(guān)頭部時(shí)
跨域請(qǐng)求的攔截
首先我們俗稱(chēng)的跨域类腮,也就是瀏覽器的同源策略
同源:協(xié)議、域名蛉加、端口號(hào)相同
同站:二級(jí)域名一致即可(對(duì)協(xié)議和端口號(hào)沒(méi)有要求)
所以蚜枢,跨域請(qǐng)求的攔截是瀏覽器干的。
如果服務(wù)端攔截针饥,那每個(gè) Server 都要專(zhuān)門(mén)要為瀏覽器實(shí)現(xiàn)一個(gè)攔截策略厂抽,這根本不現(xiàn)實(shí)。另外丁眼,服務(wù)端就算是想攔截筷凤,也沒(méi)法判斷請(qǐng)求是否跨域,HTTP Reqeust 的所有 Header 都是可以被篡改的苞七,它用什么去判斷請(qǐng)求是否跨域呢藐守?很明顯服務(wù)端心有余而力不足啊蹂风!
什么時(shí)候攔截
請(qǐng)求一定是先發(fā)出去(預(yù)檢請(qǐng)求/簡(jiǎn)單請(qǐng)求的跨域請(qǐng)求)卢厂,在返回來(lái)的時(shí)候被瀏覽器攔截了,如果請(qǐng)求是有返回值的惠啄,會(huì)被瀏覽器隱藏掉慎恒。
預(yù)檢請(qǐng)求
什么條件下會(huì)發(fā)送預(yù)檢請(qǐng)求?
非簡(jiǎn)單請(qǐng)求:
- 請(qǐng)求方法是除 GET撵渡、POST融柬、HEAD 之外的請(qǐng)求方法
- 請(qǐng)求的首部包含除了 Accept(可以接受的媒體類(lèi)型)、Content-Type(實(shí)體主體的媒體類(lèi)型)姥闭、Accept-Language丹鸿、Content-Language 之外的請(qǐng)求頭
- Content-Type 的值是除了 text/plain、application/x-www-form-urlencoded棚品、multipart/form-data 之外的值
- 請(qǐng)求中的任意 XMLHttpRequest 對(duì)象注冊(cè)了任何事件監(jiān)聽(tīng)器靠欢;XMLHttpRequest 對(duì)象可以使用 XMLHttpRequest.upload 屬性訪問(wèn)。
- 請(qǐng)求中使用了 ReadableStream 對(duì)象铜跑。
我們發(fā)現(xiàn)门怪,在發(fā)送非簡(jiǎn)單請(qǐng)求之前(真正的請(qǐng)求),瀏覽器會(huì)先發(fā)送一個(gè) Preflight 請(qǐng)求锅纺,也就是我們常說(shuō)的預(yù)檢請(qǐng)求掷空,它的方法為 OPTIONS。
這也就是為什么有的時(shí)候我們明明只發(fā)了一個(gè)請(qǐng)求,在 Network 里卻看到兩個(gè)坦弟。
預(yù)檢請(qǐng)求有一個(gè)很重要的作用就是 - 詢問(wèn)服務(wù)端是不是允許這次請(qǐng)求护锤,如果當(dāng)前請(qǐng)求是個(gè)跨域的請(qǐng)求,你可以理解為:詢問(wèn)服務(wù)端是不是允許請(qǐng)求在當(dāng)前域下跨域發(fā)送酿傍。
當(dāng)然烙懦,它還有其他的作用,比如 詢問(wèn) 服務(wù)端支持哪些 HTTP 方法赤炒。
預(yù)檢的過(guò)程
當(dāng)預(yù)檢請(qǐng)求到達(dá)服務(wù)端時(shí)氯析,服務(wù)端是不會(huì)真正執(zhí)行這個(gè)請(qǐng)求的邏輯的,只會(huì)在這個(gè)請(qǐng)求上返回一些 HTTP Header莺褒,沒(méi)有響應(yīng)體掩缓。以此來(lái)告訴客戶端是不是要發(fā)送真正的請(qǐng)求。
如果服務(wù)端告訴客戶端遵岩,請(qǐng)求是允許被發(fā)送的你辣,那真正的請(qǐng)求才會(huì)發(fā)出去。這時(shí)服務(wù)端才會(huì)真正執(zhí)行請(qǐng)求接口的邏輯旷余。
所以绢记,如果你發(fā)送的是一個(gè)簡(jiǎn)單請(qǐng)求,這個(gè)請(qǐng)求不管是不是會(huì)受到跨域的限制正卧,只要發(fā)出去了,一定會(huì)在服務(wù)端被執(zhí)行跪解,瀏覽器只是隱藏了返回值而已炉旷。
總結(jié)
- 簡(jiǎn)單請(qǐng)求:不管是否跨域,只要發(fā)出去了叉讥,一定會(huì)到達(dá)服務(wù)端并被執(zhí)行窘行,瀏覽器只會(huì)隱藏返回值(攔截響應(yīng))
- 復(fù)雜請(qǐng)求:先發(fā)預(yù)檢,預(yù)檢不會(huì)真正執(zhí)行業(yè)務(wù)邏輯图仓,預(yù)檢通過(guò)后才會(huì)發(fā)送真正請(qǐng)求并在服務(wù)端被執(zhí)行