没有办法将其与最新的 Web 浏览器区分开来。
W3C 规范:
以下步骤描述了用户代理对于简单的跨域请求必须执行的操作:
应用发出请求步骤并在发出请求时遵守以下请求规则。
如果未设置手动重定向标志并且响应的 HTTP 状态代码为 301、302、303、307 或 308应用重定向步骤。
如果最终用户取消请求应用中止步骤。
如果出现网络错误如果出现 DNS 错误、TLS 协商失败或其他类型的网络错误,请应用网络错误步骤 http://www.w3.org/TR/cors/#network-error-steps。不请求任何类型的最终用户交互。
注意:这不包括指示某种类型错误的 HTTP 响应,例如 HTTP 状态代码 410。
否则执行资源共享检查。如果返回失败,请应用网络错误步骤。否则,如果返回pass,则终止该算法,并将跨域请求状态设置为成功。实际上并不终止请求。
正如您所读到的,网络错误不包括包含错误的 HTTP 响应,这就是为什么您将始终获得 0 作为状态代码,以及“”作为错误。
Source http://www.w3.org/TR/cors/#simple-cross-origin-request
Note:以下示例是使用 Google Chrome 版本 43.0.2357.130 并针对我为模拟 OP 一而创建的环境制作的。设置它的代码位于答案的底部。
我认为解决这个问题的方法是通过 HTTP 而不是 HTTPS 发出辅助请求这个答案 https://stackoverflow.com/a/31148335/3219633但我记得这是不可能的,因为较新版本的浏览器会阻止混合内容。
这意味着如果您使用 HTTPS,Web 浏览器将不允许通过 HTTP 发出请求,反之亦然。
几年前就出现了这种情况,但较旧的 Web 浏览器版本(例如低于 23 版本的 Mozilla Firefox)允许这样做。
关于它的证据:
使用 Web 浏览器控制台从 HTTPS 发出 HTTP 请求
var request = new XMLHttpRequest();
request.open('GET', "http://localhost:8001", true);
request.onload = function () {
console.log(request.responseText);
};
request.onerror = function () {
console.log(request.responseText);
};
request.send();
将导致以下错误:
混合内容:页面位于 'https://本地主机:8000/ https://localhost:8000/'通过 HTTPS 加载,但请求了不安全的 XMLHttpRequest 端点 'http://本地主机:8001/ http://localhost:8001/'。该请求已被阻止;内容必须通过 HTTPS 提供。
如果您尝试以添加 Iframe 等其他方式执行此操作,浏览器控制台中也会出现相同的错误。
<iframe src="http://localhost:8001"></iframe>
使用Socket连接也是作为答案发布 https://stackoverflow.com/a/31148910/3219633,我很确定结果会相同/相似,但我已经尝试过。
尝试使用 HTTPS 从 Web 浏览器打开到非安全套接字端点的套接字连接将导致混合内容错误。
new WebSocket("ws://localhost:8001", "protocolOne");
1) 混合内容:页面位于 'https://本地主机:8000/ https://localhost:8000/' 通过 HTTPS 加载,但尝试连接到不安全的 WebSocket 端点 'ws://localhost:8001/'。该请求已被阻止;此端点必须可通过 WSS 使用。
2) 未捕获的 DOMException:无法构造“WebSocket”:可能无法从通过 HTTPS 加载的页面发起不安全的 WebSocket 连接。
然后我尝试连接到 wss 端点,看看是否可以读取有关网络连接错误的一些信息:
var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
console.log(e);
}
在服务器关闭的情况下执行上面的代码片段会导致:
与“wss://localhost:8001/”的 WebSocket 连接失败:连接建立时出错:net::ERR_CONNECTION_REFUSED
在服务器打开的情况下执行上面的代码片段
与“wss://localhost:8001/”的 WebSocket 连接失败:WebSocket 打开握手已取消
但同样,“onerror 函数”输出到控制台的错误没有任何提示来区分另一个错误。
使用代理作为这个答案建议 https://stackoverflow.com/a/31366144/3219633%5C%5C可以工作,但前提是“目标”服务器具有公共访问权限。
这里的情况并非如此,因此尝试在这种情况下实现代理将导致我们遇到同样的问题。
创建 Node.js HTTPS 服务器的代码:
我创建了两个使用自签名证书的 Nodejs HTTPS 服务器:
目标服务器.js:
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('./certs2/key.pem'),
cert: fs.readFileSync('./certs2/key-cert.pem')
};
https.createServer(options, function (req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.writeHead(200);
res.end("hello world\n");
}).listen(8001);
应用程序服务器.js:
var https = require('https');
var fs = require('fs');
var options = {
key: fs.readFileSync('./certs/key.pem'),
cert: fs.readFileSync('./certs/key-cert.pem')
};
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
为了使其工作,您需要安装 Nodejs,需要为每个服务器生成单独的证书并将其相应地存储在文件夹 certs 和 certs2 中。
要运行它只需执行node applicationServer.js
and node targetServer.js
在终端中(以 ubuntu 为例)。