Network出現(xiàn)兩次相同請(qǐng)求?我來(lái)解答

今天工作的時(shí)候吴叶,項(xiàng)目經(jīng)理反饋了一個(gè)問(wèn)題:Network中出現(xiàn)了兩個(gè)相同的請(qǐng)求阐虚,而我代碼中只請(qǐng)求了一次。鞍雎薄实束?又踩坑了奥秆?在研究了一番之后,發(fā)現(xiàn)還有這種操作咸灿?构订!

出現(xiàn)的狀況

Network中出現(xiàn)了兩個(gè)相同的請(qǐng)求(如圖),兩個(gè)發(fā)起了同樣的請(qǐng)求析显,花的時(shí)間卻不同鲫咽,一個(gè)55ms,一個(gè)花了294ms谷异。


兩個(gè)相同的請(qǐng)求

什么情況啊锦聊?研究了一番歹嘹,我發(fā)現(xiàn)有一個(gè)地方是不同的,Request Method孔庭!
請(qǐng)求時(shí)間短的Request Method是OPTIONS尺上,并且返回值為空。


Request Method:OPTIONS

請(qǐng)求時(shí)間長(zhǎng)的Request Method是GET圆到。


Request Method:GET

為什么出現(xiàn)這種情況

原以為ajax請(qǐng)求只有HTTP的Request Method只有GET與POST兩種怎抛,后來(lái)發(fā)現(xiàn)還有HEAD、PUT芽淡、DELETE马绝、OPTIONS……的區(qū)別。

本地環(huán)境跑公司項(xiàng)目的時(shí)候挣菲,每次POST之前富稻,為啥瀏覽器還偷偷給我來(lái)一次沒(méi)有返回的OPTIONS請(qǐng)求?

原來(lái)白胀,瀏覽器在某些請(qǐng)求中椭赋,在正式通信前會(huì)增加一次HTTP查詢(xún)請(qǐng)求,稱(chēng)為"預(yù)檢"請(qǐng)求(preflight)或杠。

瀏覽器先詢(xún)問(wèn)服務(wù)器哪怔,當(dāng)前網(wǎng)頁(yè)所在的域名是否在服務(wù)器的許可名單之中,以及可以使用哪些HTTP動(dòng)詞和頭信息字段向抢。只有得到肯定答復(fù)认境,瀏覽器才會(huì)發(fā)出正式的XMLHttpRequest請(qǐng)求,否則就報(bào)錯(cuò)笋额。

CORS了解一下

CORS是一個(gè)W3C標(biāo)準(zhǔn)元暴,全稱(chēng)是"跨域資源共享"(Cross-origin resource sharing)。

它允許瀏覽器向跨源服務(wù)器兄猩,發(fā)XMLHttpRequest請(qǐng)求茉盏,從而克服了AJAX只能同源使用的限制鉴未。

CORS需要瀏覽器和服務(wù)器同時(shí)支持。目前鸠姨,所有瀏覽器都支持該功能铜秆,IE瀏覽器不能低于IE10。
整個(gè)CORS通信過(guò)程讶迁,都是瀏覽器自動(dòng)完成连茧,不需要用戶(hù)參與。對(duì)于開(kāi)發(fā)者來(lái)說(shuō)巍糯,CORS通信與同源的AJAX通信沒(méi)有差別啸驯,代碼完全一樣。瀏覽器一旦發(fā)現(xiàn)AJAX請(qǐng)求跨源祟峦,就會(huì)自動(dòng)添加一些附加的頭信息罚斗,有時(shí)還會(huì)多出一次附加的請(qǐng)求,但用戶(hù)不會(huì)有感覺(jué)宅楞。
因此针姿,實(shí)現(xiàn)CORS通信的關(guān)鍵是服務(wù)器。只要服務(wù)器實(shí)現(xiàn)了CORS接口厌衙,就可以跨源通信距淫。

兩種請(qǐng)求

瀏覽器將CORS請(qǐng)求分為兩類(lèi):簡(jiǎn)單請(qǐng)求(simple request)和非簡(jiǎn)單請(qǐng)求(not-so-simple request)。

同時(shí)滿(mǎn)足以下條件婶希,就是簡(jiǎn)單請(qǐng)求:

(1) 請(qǐng)求方法是以下三種方法之一: HEAD GET POST
(2)HTTP的頭信息不超出以下幾種字段:Accept Accept-Language Content-Language Last-Event-ID
Content-Type:只限于三個(gè)值application/x-www-form-urlencoded榕暇、multipart/form-data、text/plain

簡(jiǎn)單請(qǐng)求

對(duì)于簡(jiǎn)單請(qǐng)求饲趋,瀏覽器直接發(fā)出CORS請(qǐng)求拐揭。具體來(lái)說(shuō),就是在頭信息之中奕塑,增加一個(gè)Origin字段堂污。
Origin字段用來(lái)說(shuō)明,本次請(qǐng)求來(lái)自哪個(gè)源(協(xié)議 + 域名 + 端口)龄砰。服務(wù)器根據(jù)這個(gè)值盟猖,決定是否同意這次請(qǐng)求。

如果Origin指定的源换棚,不在許可范圍內(nèi)式镐,服務(wù)器會(huì)返回一個(gè)正常的HTTP回應(yīng)。瀏覽器發(fā)現(xiàn)固蚤,這個(gè)回應(yīng)的頭信息沒(méi)有包含Access-Control-Allow-Origin字段(詳見(jiàn)下文)娘汞,就知道出錯(cuò)了,從而拋出一個(gè)錯(cuò)誤夕玩,被XMLHttpRequest的onerror回調(diào)函數(shù)捕獲你弦。注意惊豺,這種錯(cuò)誤無(wú)法通過(guò)狀態(tài)碼識(shí)別,因?yàn)镠TTP回應(yīng)的狀態(tài)碼有可能是200禽作。

如果Origin指定的域名在許可范圍內(nèi)尸昧,服務(wù)器返回的響應(yīng),會(huì)多出幾個(gè)頭信息字段旷偿。都以Access-Control- 開(kāi)頭:

(1)Access-Control-Allow-Origin

該字段是必須的烹俗。它的值要么是請(qǐng)求時(shí)Origin字段的值,要么是一個(gè)*萍程,表示接受任意域名的請(qǐng)求幢妄。

需要注意的是,如果要發(fā)送Cookie茫负,Access-Control-Allow-Origin就不能設(shè)為星號(hào)磁浇,必須指定明確的、與請(qǐng)求網(wǎng)頁(yè)一致的域名朽褪。同時(shí),Cookie依然遵循同源政策无虚,只有用服務(wù)器域名設(shè)置的Cookie才會(huì)上傳缔赠,其他域名的Cookie并不會(huì)上傳,且(跨源)原網(wǎng)頁(yè)代碼中的document.cookie也無(wú)法讀取服務(wù)器域名下的Cookie友题。
(2)Access-Control-Allow-Credentials

該字段可選嗤堰。它的值是一個(gè)布爾值,表示是否允許發(fā)送Cookie度宦。默認(rèn)情況下踢匣,Cookie不包括在CORS請(qǐng)求之中。設(shè)為true戈抄,即表示服務(wù)器明確許可离唬,Cookie可以包含在請(qǐng)求中,一起發(fā)給服務(wù)器划鸽。這個(gè)值也只能設(shè)為true输莺,如果服務(wù)器不要瀏覽器發(fā)送Cookie,刪除該字段即可裸诽。

(3)Access-Control-Expose-Headers

該字段可選嫂用。CORS請(qǐng)求時(shí),XMLHttpRequest對(duì)象的getResponseHeader()方法只能拿到6個(gè)基本字段:Cache-Control丈冬、Content-Language嘱函、Content-Type、Expires埂蕊、Last-Modified往弓、Pragma疏唾。如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定亮航。

非簡(jiǎn)單請(qǐng)求

非簡(jiǎn)單請(qǐng)求是那種對(duì)服務(wù)器有特殊要求的請(qǐng)求荸实,比如請(qǐng)求方法是PUT或DELETE,或者Content-Type字段的類(lèi)型是application/json缴淋。

非簡(jiǎn)單請(qǐng)求的CORS請(qǐng)求准给,會(huì)在正式通信之前,增加一次HTTP查詢(xún)請(qǐng)求重抖,稱(chēng)為"預(yù)檢"請(qǐng)求(preflight)露氮。

瀏覽器先詢(xún)問(wèn)服務(wù)器,當(dāng)前網(wǎng)頁(yè)所在的域名是否在服務(wù)器的許可名單之中钟沛,以及可以使用哪些HTTP動(dòng)詞和頭信息字段畔规。只有得到肯定答復(fù),瀏覽器才會(huì)發(fā)出正式的XMLHttpRequest請(qǐng)求恨统,否則就報(bào)錯(cuò)叁扫。

在頁(yè)面域名與接口域名不一致的情況下,就出現(xiàn)了每次請(qǐng)求前先發(fā)送一個(gè)options請(qǐng)求的問(wèn)題畜埋。

OPTIONS請(qǐng)求頭信息中莫绣,除了Origin字段,還至少會(huì)多兩個(gè)特殊字段:

(1)Access-Control-Request-Method

該字段是必須的悠鞍,用來(lái)列出瀏覽器的CORS請(qǐng)求會(huì)用到哪些HTTP方法对室。

(2)Access-Control-Request-Headers

該字段是一個(gè)逗號(hào)分隔的字符串,指定瀏覽器CORS請(qǐng)求會(huì)額外發(fā)送的頭信息字段咖祭。



至于其他亂七八糟的字段掩宜,現(xiàn)在的我還用不到也不懂,將會(huì)慢慢深入了解么翰。

服務(wù)器收到預(yù)檢請(qǐng)求后牺汤,檢查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后硬鞍,確認(rèn)允許跨源請(qǐng)求慧瘤,就可以做出回應(yīng)。

上面的HTTP回應(yīng)中固该,關(guān)鍵的是Access-Control-Allow-Origin字段锅减,表示http://lizard.qa.nt.ctripcorp.com可以請(qǐng)求數(shù)據(jù)。該字段也可以設(shè)為星號(hào)伐坏,表示同意任意跨源請(qǐng)求怔匣。

如果瀏覽器否定了"預(yù)檢"請(qǐng)求,會(huì)返回一個(gè)正常的HTTP回應(yīng),但是沒(méi)有任何CORS相關(guān)的頭信息字段每瞒。這時(shí)金闽,瀏覽器就會(huì)認(rèn)定,服務(wù)器不同意預(yù)檢請(qǐng)求剿骨,因此觸發(fā)一個(gè)錯(cuò)誤代芜,被XMLHttpRequest對(duì)象的onerror回調(diào)函數(shù)捕獲∨ɡ控制臺(tái)會(huì)打印出如下的報(bào)錯(cuò)信息挤庇。

XMLHttpRequest cannot load http://lizard.qa.nt.ctripcorp.com
Origin http://lizard.qa.nt.ctripcorp.com is not allowed by Access-Control-Allow-Origin.

其他字段中Access-Control-Max-Age 用來(lái)指定本次預(yù)檢請(qǐng)求的有效期,單位為秒贷掖。該字段可選嫡秕。

與JSONP的對(duì)比

CORS與JSONP的使用目的相同,但是比JSONP更強(qiáng)大苹威。

JSONP只支持GET請(qǐng)求昆咽,JSONP的優(yōu)勢(shì)在于支持老舊瀏覽器。

最后解決問(wèn)題的方法

解決Network出現(xiàn)兩次相同請(qǐng)求的問(wèn)題使用簡(jiǎn)單請(qǐng)求就不會(huì)遇到了牙甫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末掷酗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子窟哺,更是在濱河造成了極大的恐慌汇在,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脏答,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡亩鬼,警方通過(guò)查閱死者的電腦和手機(jī)殖告,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)雳锋,“玉大人黄绩,你說(shuō)我怎么就攤上這事$韫” “怎么了爽丹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)辛蚊。 經(jīng)常有香客問(wèn)我粤蝎,道長(zhǎng),這世上最難降的妖魔是什么袋马? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任初澎,我火速辦了婚禮,結(jié)果婚禮上虑凛,老公的妹妹穿的比我還像新娘碑宴。我一直安慰自己软啼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布延柠。 她就那樣靜靜地躺著祸挪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贞间。 梳的紋絲不亂的頭發(fā)上贿条,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音榜跌,去河邊找鬼闪唆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钓葫,可吹牛的內(nèi)容都是我干的悄蕾。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼础浮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帆调!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起豆同,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤番刊,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后影锈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體芹务,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年鸭廷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枣抱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辆床,死狀恐怖佳晶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讼载,我是刑警寧澤轿秧,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站咨堤,受9級(jí)特大地震影響菇篡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜一喘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一逸贾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦铝侵、人聲如沸灼伤。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狐赡。三九已至,卻和暖如春疟丙,著一層夾襖步出監(jiān)牢的瞬間颖侄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工享郊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留览祖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓炊琉,卻偏偏與公主長(zhǎng)得像展蒂,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子苔咪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • CORS是一個(gè)W3C標(biāo)準(zhǔn)锰悼,全稱(chēng)是"跨域資源共享"(Cross-origin resource sharing)。 ...
    奇特思維家閱讀 1,126評(píng)論 0 3
  • CORS是一個(gè)W3C標(biāo)準(zhǔn)团赏,全稱(chēng)是"跨域資源共享"(Cross-origin resource sharing)箕般。 ...
    myccy8閱讀 439評(píng)論 0 2
  • 一、簡(jiǎn)介 CORS需要瀏覽器和服務(wù)器同時(shí)支持舔清。目前丝里,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10体谒。 整個(gè)CO...
    像敏銳的狗閱讀 174評(píng)論 0 0
  • CORS是一個(gè)W3C標(biāo)準(zhǔn)丙者,全稱(chēng)是"跨域資源共享"(Cross-origin resource sharing)。 ...
    起名字太累閱讀 947評(píng)論 0 2
  • 一营密、簡(jiǎn)介 CORS需要瀏覽器和服務(wù)器同時(shí)支持。目前目锭,所有瀏覽器都支持該功能评汰,IE瀏覽器不能低于IE10。 整個(gè)CO...
    宇VS然閱讀 201評(píng)論 0 1