Невозможно отличить его от новейших веб-браузеров.
Спецификация W3C:
Следующие шаги описывают, что должны делать пользовательские агенты для простого запроса между источниками :
Примените шаги создания запроса и соблюдайте приведенные ниже правила при отправке запроса.
Если флаг ручного перенаправления не установлен и ответ имеет код состояния HTTP 301, 302, 303, 307 или 308
Примените шаги перенаправления.
Если конечный пользователь отменяет запрос
Примените шаги отмены .
Если есть сетевая ошибка.
В случае ошибок DNS, сбоя согласования TLS или других сетевых ошибок, примените шаги сетевой ошибки . Не запрашивайте никакого взаимодействия с конечным пользователем.
Примечание. Сюда не входят ответы HTTP, указывающие на какой-либо тип ошибки, например код состояния HTTP 410.
В противном случае
выполните проверку совместного использования ресурсов. Если он возвращает ошибку, примените действия по устранению сетевой ошибки. В противном случае, если он возвращает pass, завершите этот алгоритм и установите статус запроса между источниками как успех. Фактически не прекращайте запрос.
Как вы можете прочитать, сетевые ошибки не включают HTTP-ответ, содержащий ошибки, поэтому вы всегда будете получать 0 в качестве кода состояния и "" в качестве ошибки.
Источник
Примечание . Следующие примеры были сделаны с использованием Google Chrome версии 43.0.2357.130 и в среде, которую я создал для имитации OP one. Код для настройки находится внизу ответа.
Я думал, что подход Чтобы обойти это было бы сделать вторичный запрос через HTTP вместо HTTPS, как этот ответ но я вспомнил, что это невозможно из-за того, что более новые версии браузеров блокируют смешанный контент.
Это означает, что веб-браузер не будет разрешать запросы через HTTP, если вы используете HTTPS, и наоборот.
Так было несколько лет назад, но более старые версии веб-браузеров, такие как Mozilla Firefox ниже 23 версии, допускают это.
Свидетельства об этом:
Выполнение HTTP-запроса от HTTPS с использованием консоли Web Broser
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>
Использование Socket-соединения также было отправлено в качестве ответа , я был уверен, что результат будет таким же / похожим, но я попробовал.
Попытка открыть сокет-соединение от Web Broswer с использованием HTTPS к незащищенной конечной точке сокета закончится ошибками смешанного содержимого.
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);
}
Выполнение приведенного выше фрагмента с выключенным сервером приводит к:
Соединение WebSocket с 'wss: // localhost: 8001 /' не удалось: ошибка при установлении соединения: net :: ERR_CONNECTION_REFUSED
Выполнение приведенного выше фрагмента с включенным сервером
Соединение WebSocket с 'wss: // localhost: 8001 /' не удалось: рукопожатие открытия WebSocket было отменено
Но опять же, ошибка, выводимая на консоль "функцией onerror", не имеет подсказки, чтобы отличить одну ошибку от другой.
Использование прокси, как предлагает этот ответ, может работать, но только в том случае, если «целевой» сервер имеет открытый доступ.
Здесь этого не было, поэтому попытка реализовать прокси в этом сценарии приведет Нас к той же проблеме.
Код для создания HTTPS-сервера Node.js :
Я создал два HTTPS-сервера Nodejs, которые используют самозаверяющие сертификаты:
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).