背景:
1、前端Web中有两个域名,和,其中是访问主站(页面),是数据提交接口的服务器(XHR请求)
2、中用XHR调用/cerate【没有指定协议】,保存数据,写法如下:
$.ajax({url: "///create",type: 'POST',data: requestParams,dataType: 'json',xhrFields: {withCredentials: true},crossDomain: true,async: false,success: function (data) {// ...},error: function (ret) {// ...});
3、线上环境中,和的都在Nginx中配置了302强制跳转https
4、某个测试环境中,没有跳转https,有
问题:
1、线上环境,用户访问的是,调用接口为/create,跨域没有问题。
2、但是在测试环境中,测试人员直接打开了页面,调用接口就变成为/create,这里跨域预检时,的Nginx反馈302跳转,报错。
{"readyState":0,"status":0,"statusText":"NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load '/create."}
分析:
1、readtState: 0说明请求没有发出去,被浏览器拦截了,可能情况有:
url格式不对跨域失败参数错误用户取消其它...
2、这里应该是跨域失败的问题,因为报错是faild to load url
3、之前没有关注过跨域重定向问题,StackOverFlow之:
/questions/18539403/chrome-cancels-cors-xhr-upon-http-302-redirect/38810391#38810391
4、W3C标准/TR/cors/#cross-origin-request-with-preflight-0
5、总的来说,就是对于非简单请求(XHR等),当跨域预检(Option请求)时,如果出现非20X等时,会直接失败,抛出readtState: 0
解决方法:
1、在Ajax中明确https协议,避免预检时返回302
$.ajax({url: "https:///create",type: 'POST',data: requestParams,dataType: 'json',xhrFields: {withCredentials: true},crossDomain: true,async: false,success: function (data) {// ...},error: function (ret) {// ...});
2、修改测试环境下的服务器,保持和线上环境一致,不让用户走到,强制走访问页面
总结:
之前一直觉得:
请求中不指定协议,使用//自动适配页面url的协议
是一个标准规范。现在看来,对于简单请求,比如页面跳转、图片加载等确实是一个好的做法,但是对于后端接口请求这类,可能需要具体场景斟酌。这句话可以改为:
简单请求中不指定协议,使用//自动适配页面url的协议