No hay forma de diferenciarlo de los navegadores web más nuevos.
Especificación W3C:
Los pasos siguientes describen lo que deben hacer los agentes de usuario para una solicitud de origen cruzado simple :
Aplique los pasos de hacer una solicitud y observe las reglas de solicitud a continuación mientras realiza la solicitud.
Si el indicador de redireccionamiento manual no está configurado y la respuesta tiene un código de estado HTTP de 301, 302, 303, 307 o 308,
aplique los pasos de redireccionamiento.
Si el usuario final cancela la solicitud,
aplique los pasos de cancelación .
Si hay un error de red
En caso de errores de DNS, falla de negociación de TLS u otro tipo de errores de red, aplique los pasos de error de red . No solicite ningún tipo de interacción con el usuario final.
Nota: Esto no incluye las respuestas HTTP que indican algún tipo de error, como el código de estado HTTP 410.
De lo contrario,
realice una verificación de uso compartido de recursos. Si vuelve a fallar, aplique los pasos de error de red. De lo contrario, si devuelve aprobado, finalice este algoritmo y establezca el estado de la solicitud de origen cruzado en éxito. En realidad, no cancele la solicitud.
Como puede leer, los errores de red no incluyen la respuesta HTTP que incluye errores, es por eso que siempre obtendrá 0 como código de estado y "" como error.
Fuente
Nota : Los siguientes ejemplos se realizaron con la versión 43.0.2357.130 de Google Chrome y en un entorno que he creado para emular OP one. El código para configurarlo está al final de la respuesta.
Pensé que un enfoque para solucionar esto sería realizar una solicitud secundaria a través de HTTP en lugar de HTTPS como Esta respuesta, pero he recordado que no es posible debido a que las versiones más nuevas de los navegadores bloquean el contenido mixto.
Eso significa que el navegador web no permitirá una solicitud a través de HTTP si está utilizando HTTPS y viceversa.
Esto ha sido así desde hace unos años, pero las versiones anteriores del navegador web como Mozilla Firefox debajo de las versiones 23 lo permiten.
Evidencia al respecto:
Hacer una solicitud HTTP desde HTTPS usando la consola 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();
resultará en el siguiente error:
Contenido mixto: la página en ' https: // localhost: 8000 / ' se cargó a través de HTTPS, pero solicitó un extremo XMLHttpRequest inseguro ' http: // localhost: 8001 / '. Esta solicitud ha sido bloqueada; el contenido debe publicarse a través de HTTPS.
El mismo error aparecerá en la consola del navegador si intenta hacer esto de otras formas como agregar un Iframe.
<iframe src="http://localhost:8001"></iframe>
El uso de la conexión Socket también se publicó como respuesta , estaba bastante seguro de que el resultado sería el mismo / similar, pero lo he intentado.
Intentar abrir una conexión de socket desde Web Broswer usando HTTPS a un extremo de socket no seguro terminará en errores de contenido mixto.
new WebSocket("ws://localhost:8001", "protocolOne");
1) Contenido mixto: la página en ' https: // localhost: 8000 / ' se cargó a través de HTTPS, pero intentó conectarse al extremo inseguro de WebSocket 'ws: // localhost: 8001 /'. Esta solicitud ha sido bloqueada; este punto final debe estar disponible a través de WSS.
2) DOMException no detectada: no se pudo construir 'WebSocket': es posible que no se inicie una conexión WebSocket insegura desde una página cargada a través de HTTPS.
Luego intenté conectarme a un punto final wss también, consulte Si pudiera leer información sobre errores de conexión de red:
var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
console.log(e);
}
La ejecución del fragmento anterior con el servidor desactivado da como resultado:
La conexión de WebSocket a 'wss: // localhost: 8001 /' falló: Error en el establecimiento de la conexión: net :: ERR_CONNECTION_REFUSED
Ejecutando el fragmento de arriba con el servidor encendido
La conexión de WebSocket a 'wss: // localhost: 8001 /' falló: se canceló el protocolo de enlace de apertura de WebSocket
Pero nuevamente, el error que la salida de la "función onerror" a la consola no tiene ningún consejo para diferenciar un error del otro.
El uso de un proxy como sugiere esta respuesta podría funcionar, pero solo si el servidor "objetivo" tiene acceso público.
Este no fue el caso aquí, por lo que intentar implementar un proxy en este escenario nos llevará al mismo problema.
Código para crear el servidor HTTPS Node.js :
Creé dos servidores HTTPS de Nodejs, que usan certificados autofirmados:
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);
Para que funcione, debe tener Nodejs instalado, debe generar certificados separados para cada servidor y almacenarlos en las carpetas certs y certs2 en consecuencia.
Para ejecutarlo, simplemente ejecute node applicationServer.js
y node targetServer.js
en una terminal (ejemplo de ubuntu).