最新のWebブラウザと区別する方法はありません。
W3C仕様:
以下の手順は、単純なクロスオリジンリクエストに対してユーザーエージェントが実行する必要があることを示しています。
リクエストを行う際は、リクエストの作成手順を適用し、以下のリクエストルールを遵守してください。
手動リダイレクトフラグが設定されておらず、応答のHTTPステータスコードが301、302、303、307、または308
の場合リダイレクト手順を適用します。
エンドユーザーがリクエストをキャンセルした場合、
中止手順を適用します。
ネットワークエラーがある
場合DNSエラー、TLSネゴシエーションエラー、またはその他のタイプのネットワークエラーの場合は、ネットワークエラーの手順を適用します。エンドユーザーの操作は一切要求しないでください。
注:これには、HTTPステータスコード410など、ある種のエラーを示すHTTP応答は含まれません。
それ以外の場合は
、リソース共有チェックを実行します。失敗した場合は、ネットワークエラーの手順を適用します。それ以外の場合、合格を返した場合、このアルゴリズムを終了し、クロスオリジンリクエストのステータスを成功に設定します。実際にリクエストを終了しないでください。
ご覧のとおり、ネットワークエラーには、エラーを含むHTTP応答が含まれていません。そのため、ステータスコードとして常に0が返され、エラーとして ""が返されます。
ソース
注:次の例は、Google Chromeバージョン43.0.2357.130を使用して、OP 1をエミュレートするために作成した環境に対して作成されました。それを設定するためのコードは答えの一番下にあります。
これを回避するには、HTTPSではなくHTTPを介して2次要求を行うと思いますが、この回答は、新しいバージョンのブラウザーが混合コンテンツをブロックするため不可能であることを覚えています。
つまり、HTTPSを使用している場合、WebブラウザーはHTTPを介した要求を許可しません。逆の場合も同様です。
これは数年前からこのようになっていますが、Mozilla Firefoxなどの古いバージョンのWebブラウザーでは、バージョン23より前のバージョンで許可されています。
それについての証拠:
HTTPS usign Web Broserコンソールからの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:// localhost:8000 /」のページはHTTPS経由でロードされましたが、安全でないXMLHttpRequestエンドポイント「http:// localhost:8001 /」を要求しました。このリクエストはブロックされました。コンテンツはHTTPS経由で提供する必要があります。
iframeを追加するなど、他の方法でこれを実行しようとすると、ブラウザコンソールに同じエラーが表示されます。
<iframe src="http://localhost:8001"></iframe>
ソケット接続を使用することも回答として投稿されましたが、結果は同じ/類似のものになるとかなり確信していましたが、試してみました。
HTTPSを使用してWeb Broswerから非セキュアソケットエンドポイントへのソケット接続を開こうとすると、混合コンテンツエラーが発生します。
new WebSocket("ws://localhost:8001", "protocolOne");
1)混合コンテンツ:「https:// localhost:8000 /」のページはHTTPS経由でロードされましたが、安全でないWebSocketエンドポイント「ws:// localhost:8001 /」に接続しようとしました。このリクエストはブロックされました。このエンドポイントはWSS経由で使用できる必要があります。
2)キャッチされないDOMException: 'WebSocket'の構築に失敗しました:安全でないWebSocket接続がHTTPS経由でロードされたページから開始されない可能性があります。
次に、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関数」がコンソールに出力するエラーには、他のエラーと区別するためのヒントがありません。
この回答が示すようにプロキシを使用することは、「ターゲット」サーバーがパブリックアクセスを持っている場合にのみ機能します。
ここではそうではなかったため、このシナリオでプロキシを実装しようとすると、同じ問題が発生します。
Node.js HTTPSサーバーを作成するコード:
自己署名証明書を使用する2つのNodejs HTTPSサーバーを作成しました。
targetServer.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);
applicationServer.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
にnode targetServer.js
は、ターミナルで実行します(ubuntuの例)。