溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

WEB跨域請(qǐng)求

發(fā)布時(shí)間:2020-06-29 11:25:01 來源:網(wǎng)絡(luò) 閱讀:726 作者:ttlxihuan 欄目:web開發(fā)

web開發(fā)隨著ajax的出來帶來了革命性的變化,它改變了web的數(shù)據(jù)加載方式讓交互更友好,網(wǎng)絡(luò)資源更節(jié)省。但最初ajax考慮安全性并沒有開放跨域請(qǐng)求,隨著H5的到來ajax開放了跨域請(qǐng)求,所以ajax跨域請(qǐng)求存在兼容性,不過現(xiàn)在的瀏覽器大部分都已經(jīng)支持了。


常用跨域請(qǐng)求手段有:

  1. jsonp

  2. FORM到頁(yè)面框架

  3. HTTP服務(wù)器代理

  4. 服務(wù)器腳本轉(zhuǎn)發(fā)

  5. ajax

  6. WebSocket

  7. 插件



jsonp

這種方式是早期在ajax不支持跨域請(qǐng)求時(shí)的一種替代方案應(yīng)用非常多,在JQuery類的早期框架都集成了此功能。期原理就是通過HTML的<script>標(biāo)簽加載一個(gè)跨域的請(qǐng)求地址并指定一個(gè)隨機(jī)回調(diào)函數(shù),所連接的服務(wù)器返回指定的回調(diào)函數(shù)并增加參數(shù),標(biāo)簽加載完后會(huì)自動(dòng)執(zhí)行代碼來完成請(qǐng)求回調(diào),因此jsonp只支持GET請(qǐng)求方式,并且需要服務(wù)器作專用處理,典型的示例如:

前端代碼:(域名www.a.cn請(qǐng)求域名www.b.cn)

(function?(global)?{
????//發(fā)送請(qǐng)求
????function?request(url,?data,?callback)?{
????????function?jsonpcall(_data,?error)?{
????????????callback(_data,?error);
????????????//清理
????????????delete?global[data['jsonpcallback']];
????????????document.body.removeChild(script);
????????}
????????data?=?data?||?{};
????????//生成全局回調(diào)函數(shù)
????????data['jsonpcallback']?=?'jsonp_'?+?String(Math.random()).substr(2,?10);
????????global[data['jsonpcallback']]?=?jsonpcall;
????????var?params?=?getParamsString(data);
????????var?script?=?document.createElement('script');
????????script.type?=?'text/javascript';
????????script.src?=?url?+?(url.indexOf('?')?>=?0???'&'?:?'?')?+?params;
????????script.onerror?=?function?(event)?{
????????????jsonpcall(null,?event);
????????};
????????document.body.appendChild(script);
????}
????//轉(zhuǎn)換請(qǐng)求參數(shù)
????function?getParamsString(data,?prefix)?{
????????var?arr?=?[];
????????prefix?=?prefix?||?'';
????????for?(var?key?in?data)?{
????????????var?name?=?'';
????????????if?(!prefix)?{
????????????????name?=?key;
????????????}?else?{
????????????????name?=?prefix?+?'['?+?key?+?']';
????????????}
????????????if?(typeof?data[key]?===?'object')?{
????????????????arr.push(getParamsString(data[key],?name));
????????????}?else?{
????????????????arr.push(name?+?'='?+?data[key]);
????????????}
????????}
????????return?arr.join('&');
????}
????global.jsonp?=?request;
})(window);
//發(fā)起請(qǐng)求
jsonp('http://www.b.cn',?{id:?12},?function?()?{
????console.info(arguments);
});


服務(wù)端代碼:(域名www.b.cn,以PHP為例)


<?php
if?(empty($_GET['jsonpcallback']))?{
????header('HTTP/1.1?404?Not?Found');
????die();
}
//查數(shù)據(jù),返回結(jié)果
$data?=?[
????'status'?=>?'ok',
????'msg'?=>?'操作成功'
];
//輸出結(jié)果
echo?$_GET['jsonpcallback']?.?'('?.?json_encode($data,?JSON_UNESCAPED_UNICODE)?.?');';


這種方式請(qǐng)求不受跨域限制使用方便,兼容性好,非常適用小數(shù)據(jù)量跨域請(qǐng)求。缺點(diǎn)是只支持GET請(qǐng)求無(wú)法完成像上傳文件或其它請(qǐng)求方式的操作,服務(wù)器響應(yīng)結(jié)果專用性強(qiáng)。




FORM到頁(yè)面框架

這種方式在異步上傳文件使用非常多,通常是iframe+form結(jié)合通過form的target屬性指定到iframe的name完成異步請(qǐng)求,但iframe有部分移動(dòng)端存瀏覽器不支持,另外還有一個(gè)frameset標(biāo)簽在H5中已經(jīng)不支持。

使用這種方式跨域請(qǐng)求兼容性僅僅在PC端較好而且服務(wù)端不需要作額外處理,但移動(dòng)端上使用需要留意用戶平臺(tái)是否都支持。典型的示例如:

//?請(qǐng)求處理
function?request(form,?callback)?{
????var?iframe?=?document.createElement('iframe'),?name?=?'IFRAME-'?+?String(Math.random()).replace('.',?''),?submit?=?1;
????iframe.name?=?name,?form.target?=?name;
????iframe.onload?=?function?()?{
????????//初次加載
????????if?(submit?===?1)?{
????????????form.submit();
????????}?else?if?(submit?===?2)?{
????????????try?{
????????????????var?json?=?JSON.parse((iframe.contentDocument?||?iframe.contentWindow.document).body.innerHTML);
????????????????callback(json);
????????????}?catch?(err)?{
????????????????callback(null,?err);
????????????}
????????????document.body.removeChild(iframe);
????????}
????????submit++;
????};
????iframe.onerror?=?function?(event)?{
????????callback(null,?event);
????????document.body.removeChild(iframe);
????};
????//不能顯示標(biāo)簽
????iframe.style.display?=?'none';
????document.body.appendChild(iframe);
}

//發(fā)送請(qǐng)求
request(document.forms[0],?function(){
????console.info(arguments);
});


這種方式間接完成跨域操作,同時(shí)對(duì)服務(wù)端的代碼沒有額外要求,只需要返回一個(gè)通用的json串即可,通過這個(gè)方式可以完成GET與POST請(qǐng)求并且還可以上傳文件,最大的缺點(diǎn)是有少部分瀏覽器不支持。



HTTP服務(wù)器代理

這種方式從理論上說不需要開發(fā)額外的代碼只需要在HTTP服務(wù)器上配置代理轉(zhuǎn)發(fā)即可以滿足所有請(qǐng)求的跨域請(qǐng)求,但會(huì)額外增加服務(wù)器性能開銷,不適合于跨域請(qǐng)求過多的場(chǎng)景,畢竟服務(wù)器的資源是有限的。一般使用這種方式的基本上是小項(xiàng)目,大項(xiàng)目這么玩在硬件上開銷不容忽視。以nginx為例,典型的配置代碼有:(僅以server塊為例)

????location?/proxy?{
??????????#?resolver?114.114.114.114?223.5.5.5?valid=3600s;
??????????proxy_pass?http://www.b.com:8099/;
????}

nginx的proxy_pass做代理配置很容易,配置靈活。

  • 如果在proxy_pass中指定了詳細(xì)地址則只轉(zhuǎn)發(fā)到對(duì)應(yīng)的地址

  • 如果沒有指定地址則把當(dāng)前的地址追加到域名下

  • 如果需要指定DNS解析地址則可以增加resolver命令,但一定要保證DNS服務(wù)器正常,否則請(qǐng)求會(huì)卡住

  • 轉(zhuǎn)發(fā)可以使用IP地址和域名,如果有特定端口一定要追加上

  • 域名可以使用變量來傳入,例如:set $proxy_host "http://www.b.com:8099/";? proxy_pass $proxy_host;

  • 可以指定路徑,也可以通過if來判斷

nginx配置代理調(diào)試比較麻煩需要多注意兩個(gè)日志文件。對(duì)于配置要考慮:

  • 是否被截取即沒有進(jìn)入代理塊

  • 代理域名端口協(xié)議是否正確

  • 域名或地址是否能正常訪問



服務(wù)器腳本轉(zhuǎn)發(fā)

這種方式是通過服務(wù)器的腳本來轉(zhuǎn)發(fā),避開前端跨域請(qǐng)求,開發(fā)方便,對(duì)于配置HTTP服務(wù)器有限制或問題時(shí)是一個(gè)比較簡(jiǎn)單的替代方案。本質(zhì)與HTTP服務(wù)器代理類似,都是通過服務(wù)器來轉(zhuǎn)來,不可避免增加服務(wù)器的開銷。這種處理方式唯一的好處是開發(fā)調(diào)試容易,兼容性好。以PHP為例,典型的示例代碼如:

$url?=?$_GET['_url_'];
$input?=?file_get_contents('php://input');
$curl?=?curl_init();
curl_setopt_array($curl,?[
????CURLOPT_HTTP_VERSION?=>?CURL_HTTP_VERSION_1_1,
????CURLOPT_USERAGENT?=>?'Mozilla/5.0?(Windows?NT?10.0;?WOW64)?AppleWebKit/537.36?(KHTML,?like?Gecko)?Chrome/41.0.2272.118?Safari/537.36',
????CURLOPT_CONNECTTIMEOUT?=>?10,
????CURLOPT_TIMEOUT?=>?30,
????CURLOPT_RETURNTRANSFER?=>?true,
????CURLOPT_SSL_VERIFYPEER?=>?FALSE,?//?不驗(yàn)證證書
????CURLOPT_SSL_VERIFYHOST?=>?FALSE,?//?不驗(yàn)證域名
]);
if?($_SERVER['REQUEST_METHOD']?==?'POST')?{
????curl_setopt($curl,?CURLOPT_POST,?true);
????curl_setopt($curl,?CURLOPT_POSTFIELDS,?$input);
????curl_setopt($curl,?CURLOPT_URL,?$url);
}?else?{
????unset($_GET['_url_']);
????$params?=?http_build_query($_GET);
????curl_setopt($curl,?CURLOPT_URL,?$url?.?(strpos($url,?'?')???'&'?:?'?')?.?$params);
}
$response?=?curl_exec($curl);
$httpCode?=?curl_getinfo($curl,?CURLINFO_HTTP_CODE);
curl_close($curl);
header('HTTP/1.1?'?.?$httpCode);
echo?$response;

代碼中簡(jiǎn)單的示例通過curl發(fā)起跨域請(qǐng)求,前端只需要指定需要請(qǐng)求的跨域地址和參數(shù)即可完成請(qǐng)求操作,由于請(qǐng)求類型多樣化,所以使用代碼轉(zhuǎn)發(fā)要做到兼容所有請(qǐng)求形式則需要做較多的處理,一般用不上。




ajax

ajax支持跨域可以說可以非常理想,遺憾的時(shí)推出的晚,不過現(xiàn)在隨著瀏覽器全面支持H5使得ajax跨域請(qǐng)求變得普及起來,如果應(yīng)用平臺(tái)涉及比較老的瀏覽器則需要留意了。官方文檔:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS?在官方文檔中有比較詳細(xì)的說明。

其實(shí)從本質(zhì)上說跨域限制只是瀏覽器出于安全考慮的一個(gè)限制,而開放這個(gè)限制也需要合理安全,否則會(huì)造成比較多的跨域請(qǐng)求漏洞,因此瀏覽器對(duì)ajax跨域請(qǐng)求作了一些限制,它必需要服務(wù)器返回允許跨域響應(yīng)頭信息,才正常提供響應(yīng)結(jié)果,所以ajax跨域請(qǐng)求需要服務(wù)端額外增加響應(yīng)頭信息。

ajax跨域請(qǐng)求分為兩種場(chǎng)景:基本請(qǐng)求,預(yù)檢請(qǐng)求;并且XMLHttpRequest內(nèi)部通過指定條件強(qiáng)制判斷識(shí)別并作出相應(yīng)的操作,其中預(yù)檢請(qǐng)求會(huì)觸發(fā)CORS預(yù)檢,CORS預(yù)檢會(huì)把請(qǐng)求類型強(qiáng)制修改為OPTIONS類型向服務(wù)器發(fā)起跨域請(qǐng)求檢查服務(wù)器是否響應(yīng)允許跨域請(qǐng)求頭信息如果允許則再次發(fā)起指定的請(qǐng)求類型跨域請(qǐng)求并把響應(yīng)內(nèi)容注入到ajax響應(yīng)內(nèi)容中,而基本請(qǐng)求是直接發(fā)起指定請(qǐng)求類型的跨域請(qǐng)求。兩種請(qǐng)求場(chǎng)景均需要跨域服務(wù)器返回允許跨域響應(yīng)頭信息,響應(yīng)狀態(tài)等頭信息不會(huì)受影響。

常規(guī)請(qǐng)求

這種場(chǎng)景瀏覽器會(huì)直接發(fā)起請(qǐng)求,當(dāng)響應(yīng)頭信息內(nèi)容中不包含Access-Control-Allow-Origin允許頭信息時(shí)會(huì)丟棄響應(yīng)內(nèi)容并向控制臺(tái)發(fā)出Failed to load警告信息,提示服務(wù)器沒有Access-Control-Allow-Origin響應(yīng)頭信息請(qǐng)求不被允許。

條件:(需全部滿足)

  • 請(qǐng)求類型為 GET、HEAD、POST

  • 僅設(shè)置過Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport-Width、Width頭信息,或使用默認(rèn)的不設(shè)置頭信息

  • Content-Type只能設(shè)置為application/x-www-form-urlencoded、multipart/form-data、text/plain,或者不設(shè)置

  • 在請(qǐng)求中沒有使用過XMLHttpRequestUpload事件監(jiān)聽。XMLHttpRequestUpload是通過XMLHttpRequest對(duì)象的upload屬性獲取的一個(gè)上傳進(jìn)度對(duì)象,可以獲取上傳進(jìn)度數(shù)據(jù)。

  • 請(qǐng)求中沒有使用ReadableStream對(duì)象。ReadableStream大部分瀏覽器還不支持,是一個(gè)獲取響應(yīng)二進(jìn)度流的對(duì)象處理器。

示例代碼:(只在不觸犯以上任何一個(gè)條件即可)

(function?(global)?{
????function?request(url,?callback,?data,?method)?{
????????var?xmlHttp?=?new?XMLHttpRequest();
????????var?params?=?getParamsString(data?||?{});
????????method?=?method?||?'GET';
????????if?(method.toUpperCase()?===?'POST')?{
????????????xmlHttp.open(method,?url,?true);
????????????xmlHttp.setRequestHeader('Content-Type',?'application/x-www-form-urlencoded;');
????????????xmlHttp.send(params);
????????}?else?{
????????????xmlHttp.open(method,?url?+?(url.indexOf('?')?>=?0???'&'?:?'?')?+?params,?true);
????????????xmlHttp.send(null);
????????}
????????xmlHttp.onreadystatechange?=?function?()?{
????????????if?(xmlHttp.readyState?==?4)?{
????????????????try?{
????????????????????if?(xmlHttp.status?==?200)?{
????????????????????????var?json?=?JSON.parse(xmlHttp.responseText);
????????????????????????callback(json);
????????????????????}?else?{
????????????????????????callback(null,?xmlHttp.responseText);
????????????????????}
????????????????}?catch?(err)?{
????????????????????callback(null,?err);
????????????????}
????????????}
????????};
????}
????//轉(zhuǎn)換請(qǐng)求參數(shù)
????function?getParamsString(data,?prefix)?{
????????var?arr?=?[];
????????prefix?=?prefix?||?'';
????????for?(var?key?in?data)?{
????????????var?name?=?'';
????????????if?(!prefix)?{
????????????????name?=?key;
????????????}?else?{
????????????????name?=?prefix?+?'['?+?key?+?']';
????????????}
????????????if?(typeof?data[key]?===?'object')?{
????????????????arr.push(getParamsString(data[key],?name));
????????????}?else?{
????????????????arr.push(name?+?'='?+?data[key]);
????????????}
????????}
????????return?arr.join('&');
????}
????global.ajax?=?request;
})(window);
//發(fā)起請(qǐng)求
ajax('https://www.b.cn/',?function?()?{
????console.info(arguments);
});


預(yù)檢請(qǐng)求

這種場(chǎng)景請(qǐng)求瀏覽器會(huì)強(qiáng)制把請(qǐng)求類型改為OPTIONS類型發(fā)起預(yù)檢跨域請(qǐng)求,當(dāng)響應(yīng)頭信息內(nèi)容中不包含Access-Control-Allow-Origin允許頭信息時(shí)會(huì)丟棄響應(yīng)內(nèi)容并向控制臺(tái)發(fā)出Failed to load警告信息,提示服務(wù)器沒有Access-Control-Allow-Origin響應(yīng)頭信息請(qǐng)求不被允許;如果響應(yīng)頭信息全部允許跨域請(qǐng)求則瀏覽器會(huì)再次發(fā)送指定請(qǐng)求類型的跨域請(qǐng)求到服務(wù)器并獲取本次響應(yīng)內(nèi)容注入到ajax的響應(yīng)內(nèi)容中。

條件:(任意條滿足)

  • 請(qǐng)求類型指定為:PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH

  • 設(shè)置了Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport-Width、Width之外的頭信息

  • 設(shè)置Content-Type是為application/x-www-form-urlencoded、multipart/form-data、text/plain之外的類型

  • 在請(qǐng)求中使用過XMLHttpRequestUpload事件監(jiān)聽

  • 請(qǐng)求中使用ReadableStream對(duì)象

示例代碼:(強(qiáng)制增加一個(gè)特殊頭信息即可)

(function?(global)?{
????function?request(url,?callback,?data,?method)?{
????????var?xmlHttp?=?new?XMLHttpRequest();
????????var?params?=?getParamsString(data?||?{});
????????method?=?method?||?'GET';
????????if?(method.toUpperCase()?===?'POST')?{
????????????xmlHttp.open(method,?url,?true);
????????????xmlHttp.setRequestHeader('Ajax-Request',?'1');
????????????xmlHttp.setRequestHeader('Content-Type',?'application/x-www-form-urlencoded;');
????????????xmlHttp.send(params);
????????}?else?{
????????????xmlHttp.open(method,?url?+?(url.indexOf('?')?>=?0???'&'?:?'?')?+?params,?true);
????????????xmlHttp.setRequestHeader('Ajax-Request',?'1');
????????????xmlHttp.setRequestHeader('Content-Type',?'text/html');
????????????xmlHttp.send(null);
????????}
????????xmlHttp.onreadystatechange?=?function?()?{
????????????if?(xmlHttp.readyState?==?4)?{
????????????????try?{
????????????????????if?(xmlHttp.status?==?200)?{
????????????????????????var?json?=?JSON.parse(xmlHttp.responseText);
????????????????????????callback(json);
????????????????????}?else?{
????????????????????????callback(null,?xmlHttp.responseText);
????????????????????}
????????????????}?catch?(err)?{
????????????????????callback(null,?err);
????????????????}
????????????}
????????};
????}
????//轉(zhuǎn)換請(qǐng)求參數(shù)
????function?getParamsString(data,?prefix)?{
????????var?arr?=?[];
????????prefix?=?prefix?||?'';
????????for?(var?key?in?data)?{
????????????var?name?=?'';
????????????if?(!prefix)?{
????????????????name?=?key;
????????????}?else?{
????????????????name?=?prefix?+?'['?+?key?+?']';
????????????}
????????????if?(typeof?data[key]?===?'object')?{
????????????????arr.push(getParamsString(data[key],?name));
????????????}?else?{
????????????????arr.push(name?+?'='?+?data[key]);
????????????}
????????}
????????return?arr.join('&');
????}
????global.ajax?=?request;
})(window);
//發(fā)起請(qǐng)求
ajax('https://www.b.cn/',?function?()?{
????console.info(arguments);
});


攜帶請(qǐng)求資源

在跨域請(qǐng)求時(shí)還允許攜帶請(qǐng)求資源如cookie,但必需設(shè)置XMLHttpRequest對(duì)象的withCredentials屬性為true,如:

xmlHttp.withCredentials?=?true;

攜帶的請(qǐng)求資源受,響應(yīng)頭信息Access-Control-Allow-Origin、Access-Control-Allow-Credentials兩個(gè)影響,Access-Control-Allow-Origin必需指定為當(dāng)前請(qǐng)求的域名,Access-Control-Allow-Credentials必需設(shè)置為true否則跨域請(qǐng)求攜帶資源失敗即服務(wù)器返回的cookie不會(huì)被記錄。跨域請(qǐng)求只受Access-Control-Allow-Origin影響,只要Access-Control-Allow-Origin允許當(dāng)前域名則請(qǐng)求可以正常獲取響應(yīng)結(jié)果。

注意:如果設(shè)置這個(gè)值,Access-Control-Allow-Origin指定為通配符有兼容問題,需要設(shè)置為對(duì)應(yīng)的域名集。


跨域請(qǐng)求響應(yīng)頭信息

這些頭信息由服務(wù)器響應(yīng),瀏覽器內(nèi)核判斷并作相應(yīng)處理。這些頭信息是預(yù)定好的,只需要按規(guī)則響應(yīng)返回給瀏覽即可完成跨域請(qǐng)求。瀏覽器對(duì)這些頭信息處理略有差異,不建議設(shè)計(jì)的太隨意畢竟安全還是比較重要的。

Access-Control-Allow-Origin

該頭信息是跨域請(qǐng)求中必需響應(yīng)的,它用來標(biāo)識(shí)服務(wù)器允許哪些請(qǐng)求來源域名共享數(shù)據(jù),一般如果沒有特別要求最好設(shè)置為指定的開放域名。如果允許任意域名使用*通配符。如果是指定一個(gè)域名并且每次請(qǐng)求該響應(yīng)頭均會(huì)變化則需要增加Vary: Origin頭信息來禁止瀏覽器的緩存。


Access-Control-Expose-Headers

該頭信息允許暴露給外部的頭信息,默認(rèn)只可以暴露服務(wù)器響應(yīng)Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma頭信息。如果想讓腳本通過XMLHttpRequest對(duì)象的getAllResponseHeaders()函數(shù)訪問到其它頭信息則可以在這里設(shè)置,多個(gè)以逗號(hào)分開也可以使用通配符*。注意預(yù)檢請(qǐng)求中詢問成功后才有效。


Access-Control-Max-Age

該狀信息用于預(yù)檢請(qǐng)求中Access-Control-Allow-Methods、Access-Control-Allow-Headers信息可以緩存多久,單位為秒,每個(gè)瀏覽器中最大秒數(shù)有限制,火狐中最大86400秒,谷歌中600秒,如果需要禁用緩存響應(yīng)返回-1即可。


Access-Control-Allow-Credentials

該頭信息是允許跨域請(qǐng)求中攜帶請(qǐng)求資源主要是cookie。只要在XMLHttpRequest對(duì)象中設(shè)置withCredentials=true同時(shí)Access-Control-Allow-Origin為當(dāng)前請(qǐng)求的域名,Access-Control-Allow-Credentials為true(字符串)即可攜帶資源請(qǐng)求。


Access-Control-Allow-Methods

該頭信息是允許跨域請(qǐng)求類型集,可以設(shè)置為指定的請(qǐng)求類型如:GET、POST、PUT、DELETE等,也可以設(shè)置為*通配符允許所有請(qǐng)求類型,默認(rèn)不設(shè)置即允許所有請(qǐng)求。該頭信息僅在預(yù)檢請(qǐng)求中有效,標(biāo)準(zhǔn)要求是當(dāng)發(fā)送OPTIONS請(qǐng)求時(shí)如果響應(yīng)中允許當(dāng)前指定請(qǐng)求類型時(shí)會(huì)自動(dòng)再發(fā)起一次指定的請(qǐng)求類型請(qǐng)求并對(duì)XMLHttpRequest對(duì)象作出回調(diào),目前各瀏覽器實(shí)現(xiàn)并不統(tǒng)一,有的瀏覽器此參數(shù)無(wú)效。


Access-Control-Allow-Headers

該頭信息用于開放額外發(fā)送給服務(wù)器的頭信息,默認(rèn)必定允許Accept、Accept-Language、Content-Language、Content-Type等常規(guī)允許頭信息設(shè)置,當(dāng)指定其它頭信息時(shí)瀏覽器啟動(dòng)預(yù)檢請(qǐng)求詢問服務(wù)器是否允許額外的這些頭信息設(shè)置,如果允許則再發(fā)送常規(guī)請(qǐng)求。開放的頭信息多個(gè)以逗號(hào)分開也可以使用通配符*(通配符有兼容問題)。如果頭信息不能匹配允許則請(qǐng)求終止不再發(fā)起常規(guī)請(qǐng)求并且XMLHttpRequest獲取響應(yīng)失敗代碼無(wú)法獲取服務(wù)器的響應(yīng)內(nèi)容(有兼容性問題部分瀏覽器還是可以獲取服務(wù)器響應(yīng)內(nèi)容)。


跨域禁止修改請(qǐng)求頭信息

這些請(qǐng)求頭信息在跨域請(qǐng)求時(shí)瀏覽器禁止代碼修改。在非跨域請(qǐng)求則允許修改。

Origin

標(biāo)記請(qǐng)求來源站點(diǎn)。


Access-Control-Request-Method

用于通知服務(wù)器真實(shí)的請(qǐng)求類型。


Access-Control-Request-Headers

用于通知服務(wù)器請(qǐng)求頭字段集,多個(gè)以逗號(hào)分開或使用通配符*


兼容性

跨域請(qǐng)求是新開放的特性在兼容性方面差異比較多,一般推薦使用常規(guī)請(qǐng)求會(huì)更理想,使用預(yù)檢模式下很多代碼或服務(wù)器均未對(duì)OPTIONS請(qǐng)求類型提供支持導(dǎo)致請(qǐng)求失敗。對(duì)于瀏覽器內(nèi)核兼容性可查看:https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Browser_compatibility



WebSocket

WebSocket是web引入的全新技術(shù),讓web端也能實(shí)現(xiàn)長(zhǎng)連接,目前兼容性?https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7?。websocket允許跨域連接并且不需要額外處理,因?yàn)槭情L(zhǎng)連接,所以web服務(wù)器需要額外調(diào)整為長(zhǎng)連接才能與終端通信。websocket連接操作簡(jiǎn)單,但服務(wù)器端需要轉(zhuǎn)換處理方式,一般應(yīng)用與游戲、直播類項(xiàng)目較多。


兼容性

WebSocket請(qǐng)求是專門為H5設(shè)計(jì)的,目前支付H5的瀏覽器均支持。在部分瀏覽器中https與http頁(yè)面中使用ws與wss有安全限制,要求https只能連接wss,而http的可以使用ws和wss。

一般在https頁(yè)面中最好使用wss協(xié)議連接,如果服務(wù)端不支持wss可以通過nginx進(jìn)行轉(zhuǎn)發(fā)把ws改為wss。



插件

增加插件可以擴(kuò)展web功能。插件不受瀏覽器過多的限制,在跨域請(qǐng)求中可以很好的發(fā)輝。缺點(diǎn)是插件的開發(fā)形式不統(tǒng)一,兼容性也不一樣,目前比較多的是flash,但flash自身的問題已經(jīng)將慢慢進(jìn)入歷史舞臺(tái)了。


向AI問一下細(xì)節(jié)

免責(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)容。

AI