Il n'y a aucun moyen de le différencier des navigateurs Web les plus récents.
Spécification W3C:
Les étapes ci-dessous décrivent ce que les agents utilisateurs doivent faire pour une simple requête cross-origin :
Appliquez les étapes de demande et respectez les règles de demande ci-dessous lors de la demande.
Si l'indicateur de redirection manuelle n'est pas défini et que la réponse a un code d'état HTTP 301, 302, 303, 307 ou 308,
appliquez les étapes de redirection.
Si l'utilisateur final annule la demande
Appliquez les étapes d'abandon.
En cas d' erreur réseau En cas d'erreurs DNS, d'échec de la négociation TLS ou de tout autre type d'erreurs réseau, appliquez les étapes d'erreur réseau . Ne demandez aucun type d'interaction avec l'utilisateur final.
Remarque: cela n'inclut pas les réponses HTTP indiquant un type d'erreur, tel que le code d'état HTTP 410.
Sinon,
effectuez une vérification du partage des ressources. S'il renvoie un échec, appliquez les étapes d'erreur réseau. Sinon, s'il renvoie pass, arrêtez cet algorithme et définissez le statut de la requête cross-origin sur succès. Ne mettez pas réellement fin à la demande.
Comme vous pouvez le lire, les erreurs réseau n'incluent pas la réponse HTTP qui inclut les erreurs, c'est pourquoi vous obtiendrez toujours 0 comme code d'état et "" comme erreur.
La source
Remarque : les exemples suivants ont été réalisés à l'aide de la version 43.0.2357.130 de Google Chrome et dans un environnement que j'ai créé pour émuler l'OP one. Le code de la configuration est au bas de la réponse.
Je pensais qu'une approche pour contourner ce problème serait de faire une requête secondaire sur HTTP au lieu de HTTPS comme réponse, mais je me suis souvenu que ce n'est pas possible car les nouvelles versions des navigateurs bloquent le contenu mixte.
Cela signifie que le navigateur Web n'autorisera pas une requête via HTTP si vous utilisez HTTPS et vice versa.
C'est comme ça depuis quelques années, mais les anciennes versions du navigateur Web comme Mozilla Firefox en dessous des versions 23 le permettent.
Preuve à ce sujet:
Faire une requête HTTP depuis HTTPS en utilisant 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();
entraînera l'erreur suivante:
Contenu mixte: la page " https: // localhost: 8000 / " a été chargée via HTTPS, mais a demandé un point de terminaison XMLHttpRequest non sécurisé " http: // localhost: 8001 / ". Cette demande a été bloquée; le contenu doit être diffusé via HTTPS.
La même erreur apparaîtra dans la console du navigateur si vous essayez de le faire d'une autre manière que l'ajout d'un Iframe.
<iframe src="http://localhost:8001"></iframe>
L'utilisation de la connexion Socket a également été publiée en tant que réponse , j'étais à peu près sûr que le résultat sera le même / similaire, mais j'ai essayé.
Si vous essayez d'ouvrir une connexion de socket à partir de Web Broswer à l'aide de HTTPS vers un point de terminaison de socket non sécurisé, des erreurs de contenu mixte se termineront.
new WebSocket("ws://localhost:8001", "protocolOne");
1) Contenu mixte: la page à l' adresse ' https: // localhost: 8000 / ' a été chargée via HTTPS, mais a tenté de se connecter au point de terminaison WebSocket non sécurisé 'ws: // localhost: 8001 /'. Cette demande a été bloquée; ce point de terminaison doit être disponible via WSS.
2) Exception DOMException non interceptée: échec de la construction de 'WebSocket': une connexion WebSocket non sécurisée peut ne pas être initiée à partir d'une page chargée via HTTPS.
Ensuite, j'ai essayé de me connecter à un point de terminaison wss aussi voir si je pouvais lire des informations sur les erreurs de connexion réseau:
var exampleSocket = new WebSocket("wss://localhost:8001", "protocolOne");
exampleSocket.onerror = function(e) {
console.log(e);
}
L'exécution de l'extrait de code ci-dessus avec le serveur désactivé entraîne:
Échec de la connexion WebSocket à 'wss: // localhost: 8001 /': erreur lors de l'établissement de la connexion: net :: ERR_CONNECTION_REFUSED
Exécution de l'extrait de code ci-dessus avec le serveur activé
Échec de la connexion WebSocket à 'wss: // localhost: 8001 /': la négociation d'ouverture de WebSocket a été annulée
Mais encore une fois, l'erreur que la "fonction onerror" sortie vers la console n'a pas d'astuce pour différencier une erreur de l'autre.
L'utilisation d'un proxy comme le suggère cette réponse pourrait fonctionner mais seulement si le serveur "cible" a un accès public.
Ce n'était pas le cas ici, donc essayer d'implémenter un proxy dans ce scénario nous conduira au même problème.
Code pour créer le serveur HTTPS Node.js :
J'ai créé deux serveurs HTTPS Nodejs, qui utilisent des certificats auto-signés:
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);
Pour que cela fonctionne, vous devez installer Nodejs, vous devez générer des certificats séparés pour chaque serveur et les stocker dans les dossiers certs et certs2 en conséquence.
Pour l'exécuter node applicationServer.js
, exécutez simplement et node targetServer.js
dans un terminal (exemple ubuntu).