Non c'è modo di differenziarlo dai browser Web più recenti.
Specifica W3C:
I passaggi seguenti descrivono cosa devono fare i programmi utente per una semplice richiesta cross-origin :
Applica la procedura di creazione di una richiesta e osserva le regole di richiesta di seguito durante la richiesta.
Se il flag di reindirizzamento manuale non è impostato e la risposta ha un codice di stato HTTP 301, 302, 303, 307 o 308,
applicare i passaggi di reindirizzamento.
Se l'utente finale annulla la richiesta,
applicare i passaggi di interruzione.
In caso di errore di rete In caso di errori DNS, errore di negoziazione TLS o altri tipi di errori di rete, applicare i passaggi dell'errore di rete . Non richiedere alcun tipo di interazione con l'utente finale.
Nota: questo non include le risposte HTTP che indicano qualche tipo di errore, come il codice di stato HTTP 410.
In caso contrario,
eseguire un controllo della condivisione delle risorse. Se restituisce un errore, applicare i passaggi di errore di rete. Altrimenti, se restituisce pass, termina questo algoritmo e imposta lo stato della richiesta cross-origin su successo. Non terminare effettivamente la richiesta.
Come puoi leggere, gli errori di rete non includono la risposta HTTP che include errori, ecco perché otterrai sempre 0 come codice di stato e "" come errore.
fonte
Nota : i seguenti esempi sono stati realizzati utilizzando Google Chrome versione 43.0.2357.130 e su un ambiente che ho creato per emulare uno OP. Il codice per impostarlo è in fondo alla risposta.
Ho pensato che un approccio per aggirare questo sarebbe fare una richiesta secondaria su HTTP invece di HTTPS come Questa risposta, ma ho ricordato che non è possibile a causa del fatto che le versioni più recenti dei browser bloccano il contenuto misto.
Ciò significa che il browser Web non consentirà una richiesta su HTTP se si utilizza HTTPS e viceversa.
È stato così da alcuni anni fa, ma le versioni precedenti del browser Web come Mozilla Firefox sotto le versioni 23 lo consentono.
Prove a riguardo:
Effettuare una richiesta HTTP da HTTPS utilizzando la console 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();
comporterà il seguente errore:
Contenuto misto: la pagina in " https: // localhost: 8000 / " è stata caricata su HTTPS, ma ha richiesto un endpoint XMLHttpRequest non sicuro " http: // localhost: 8001 / ". Questa richiesta è stata bloccata; il contenuto deve essere offerto tramite HTTPS.
Lo stesso errore apparirà nella console del browser se provi a farlo in altri modi come l'aggiunta di un Iframe.
<iframe src="http://localhost:8001"></iframe>
Anche l'utilizzo della connessione Socket è stato pubblicato come risposta , ero abbastanza sicuro che il risultato sarebbe stato lo stesso / simile ma ho provato.
Il tentativo di aprire una connessione socket dal browser Web utilizzando HTTPS a un endpoint socket non protetto finirà con errori di contenuto misto.
new WebSocket("ws://localhost:8001", "protocolOne");
1) Contenuto misto: la pagina su " https: // localhost: 8000 / " è stata caricata su HTTPS, ma ha tentato di connettersi all'endpoint WebSocket non sicuro "ws: // localhost: 8001 /". Questa richiesta è stata bloccata; questo endpoint deve essere disponibile su WSS.
2) DOMException non rilevata: impossibile costruire "WebSocket": una connessione WebSocket non sicura potrebbe non essere avviata da una pagina caricata su HTTPS.
Quindi ho provato a connettermi anche a un endpoint wss vedere Se potessi leggere alcune informazioni sugli errori di connessione di rete:
var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
console.log(e);
}
L'esecuzione dello snippet sopra con il server disattivato produce:
Connessione WebSocket a 'wss: // localhost: 8001 /' non riuscita: errore nella creazione della connessione: net :: ERR_CONNECTION_REFUSED
Esecuzione dello snippet precedente con il server attivato
Connessione WebSocket a 'wss: // localhost: 8001 /' non riuscita: l'handshake di apertura di WebSocket è stato annullato
Ma ancora una volta, l'errore che la "funzione onerror" restituisce alla console non ha alcun suggerimento per differenziare un errore dall'altro.
L'uso di un proxy come suggerisce questa risposta potrebbe funzionare, ma solo se il server "target" ha accesso pubblico.
Questo non era il caso qui, quindi provare a implementare un proxy in questo scenario ci porterà allo stesso problema.
Codice per creare il server HTTPS Node.js :
Ho creato due server HTTPS Nodejs, che utilizzano certificati autofirmati:
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);
Per farlo funzionare è necessario che Nodejs sia installato, è necessario generare certificati separati per ogni server e archiviarli nelle cartelle certs e certs2 di conseguenza.
Per eseguirlo basta eseguire node applicationServer.js
e node targetServer.js
in un terminale (esempio ubuntu).