Немає можливості відрізнити це від найновіших веб-браузерів.
Специфікація W3C:
Наведені нижче кроки описують, що агенти користувачів повинні виконувати для простого запиту між походженням :
Застосуйте кроки зробити запит та дотримуйтесь наведених нижче правил, під час оформлення запиту.
Якщо прапор перенаправлення вручну не встановлено, а відповідь має код статусу HTTP 301, 302, 303, 307 або 308,
застосуйте кроки перенаправлення.
Якщо кінцевий користувач скасує запит,
застосуйте етапи переривання.
Якщо є мережна помилка
У разі помилок DNS, помилки узгодження TLS або іншого типу мережевих помилок, застосуйте кроки мережевої помилки . Не вимагайте жодної взаємодії з кінцевим користувачем.
Примітка. Це не включає відповіді HTTP, які вказують на певний тип помилок, наприклад код HTTP статусу 410.
Інакше
проведіть перевірку обміну ресурсами. Якщо він не повертається, застосуйте кроки помилки мережі. В іншому випадку, якщо він повертає пропуск, скасуйте цей алгоритм і встановіть статус запиту перехресного походження на успіх. Насправді не припиняйте запит.
Як ви можете прочитати, мережеві помилки не включають відповідь HTTP, яка включає помилки, тому ви завжди отримаєте 0 як код статусу, а "" - як помилка.
Джерело
Примітка . Наступні приклади зроблені за допомогою версії Google Chrome 43.0.2357.130 та проти середовища, яке я створив для імітації ОП. Код до його налаштування знаходиться внизу відповіді.
Хоча я вважаю, що підхід для вирішення цього питання може бути вторинним запитом через HTTP замість HTTPS як ця відповідь, але я пам’ятав, що це неможливо через те, що новіші версії браузерів блокують змішаний контент.
Це означає, що веб-браузер не дозволить запитувати через HTTP, якщо ви використовуєте HTTPS і навпаки.
Це було подібним з декількох років тому, але старіші версії веб-браузера, такі як Mozilla Firefox, нижче його версії 23 дозволяють.
Докази про це:
Здійснення HTTP-запиту з консолі веб-браузера HTTPS
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 також було опубліковано як відповідь , я був майже впевнений, що результат буде таким же / подібним, але я спробую.
Спроба відкрити з'єднання з сокетом від веб-браузера за допомогою HTTPS до не захищеної кінцевої точки сокета закінчиться помилками змішаного вмісту.
new WebSocket("ws://localhost:8001", "protocolOne");
1) Змішаний контент: Сторінка в розділі " https: // localhost: 8000 / " була завантажена через HTTPS, але намагалася підключитися до небезпечної кінцевої точки WebSocket 'ws: // localhost: 8001 /'. Цей запит заблоковано; ця кінцева точка повинна бути доступна через WSS.
2) Uncaught 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 скасовано
Але знову ж таки помилка в тому, що "конверторна функція" виводиться на консоль, не має жодної підказки для розмежування однієї помилки від іншої.
Використання проксі-сервера, як підказує ця відповідь, може спрацювати, але лише у тому випадку, якщо "цільовий" сервер має доступ до публіки.
Тут цього не було, тому спроба впровадити проксі в цьому сценарії призведе нас до тієї ж проблеми.
Код для створення сервера 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. Потрібно генерувати окремі сертифікати для кожного сервера та зберігати їх у серцях папок та certs2 відповідно.
Для його запуску просто виконуйте node applicationServer.js
і node targetServer.js
в терміналі (приклад ubuntu).