He estado investigando mucho y no pude encontrar una manera de manejar esto. Estoy tratando de realizar una llamada jQuery ajax desde un servidor https a un servidor https de locahost que ejecuta un embarcadero con un certificado autofirmado personalizado. Mi problema es que no puedo determinar si la respuesta es una conexión rechazada o una respuesta insegura (debido a la falta de aceptación del certificado). ¿Hay alguna forma de determinar la diferencia entre ambos escenarios? Los responseText
, y statusCode
siempre son iguales en ambos casos, aunque en la consola de Chrome puedo ver una diferencia:
net::ERR_INSECURE_RESPONSE
net::ERR_CONNECTION_REFUSED
responseText
es siempre "" y statusCode
siempre es "0" para ambos casos.
Mi pregunta es, ¿cómo puedo determinar si una llamada ajax de jQuery falló debido a ERR_INSECURE_RESPONSE
o debido a ERR_CONNECTION_REFUSED
?
Una vez que se acepta el certificado, todo funciona bien, pero quiero saber si el servidor localhost está apagado o si está en funcionamiento, pero el certificado aún no ha sido aceptado.
$.ajax({
type: 'GET',
url: "https://localhost/custom/server/",
dataType: "json",
async: true,
success: function (response) {
//do something
},
error: function (xhr, textStatus, errorThrown) {
console.log(xhr, textStatus, errorThrown); //always the same for refused and insecure responses.
}
});
Incluso realizando manualmente la solicitud obtengo el mismo resultado:
var request = new XMLHttpRequest();
request.open('GET', "https://localhost/custom/server/", true);
request.onload = function () {
console.log(request.responseText);
};
request.onerror = function () {
console.log(request.responseText);
};
request.send();
fuente
function (xhr, status, msg) {...
Dudo que lo hagan, pero vale la pena intentarlo.Respuestas:
No hay forma de diferenciarlo de los navegadores web más nuevos.
Especificación W3C:
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
resultará en el siguiente error:
El mismo error aparecerá en la consola del navegador si intenta hacer esto de otras formas como agregar un 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.
Luego intenté conectarme a un punto final wss también, consulte Si pudiera leer información sobre errores de conexión de red:
La ejecución del fragmento anterior con el servidor desactivado da como resultado:
Ejecutando el fragmento de arriba con el servidor encendido
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:
applicationServer.js:
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
ynode targetServer.js
en una terminal (ejemplo de ubuntu).fuente
A partir de ahora: no hay forma de diferenciar este evento entre navegadores. Como los navegadores no proporcionan un evento para que los desarrolladores accedan. (Julio de 2015)
Esta respuesta simplemente busca proporcionar ideas para una solución potencial, albiet hacky e incompleta.
Descargo de responsabilidad: esta respuesta está incompleta ya que no resuelve por completo los problemas de OP (debido a las políticas de origen cruzado). Sin embargo, la idea en sí tiene algún mérito que se amplía aún más con: @artur grzesiak aquí , usando un proxy y ajax.
Después de un poco de investigación, no parece haber ninguna forma de verificación de errores para la diferencia entre la conexión rechazada y una respuesta insegura, al menos en la medida en que javascript proporciona una respuesta para la diferencia entre los dos.
El consenso general de mi investigación es que los certificados SSL son manejados por el navegador, por lo que hasta que el usuario acepta un certificado autofirmado, el navegador bloquea todas las solicitudes, incluidas las de un código de estado. El navegador podría (si está codificado) enviar su propio código de estado para una respuesta insegura, pero eso realmente no ayuda en nada, e incluso entonces, tendría problemas con la compatibilidad del navegador (Chrome / Firefox / IE tiene diferentes estándares. .. Una vez más)
Dado que su pregunta original era verificar el estado de su servidor entre estar activo y tener un certificado no aceptado, ¿no podría hacer una solicitud HTTP estándar como esa?
Por supuesto, esto requiere una solicitud adicional para verificar la conectividad del servidor, pero debería hacer el trabajo mediante el proceso de eliminación. Sin embargo, todavía se siente hacky, y no soy un gran admirador de la solicitud duplicada.
fuente
La respuesta de @ Schultzie es bastante cercana, pero claramente
http
, en general, no funcionaráhttps
en el entorno del navegador.Sin embargo, lo que puede hacer es utilizar un servidor intermedio (proxy) para realizar la solicitud en su nombre. El proxy debería permitir reenviar
http
solicitudes desde elhttps
origen o cargar contenido desde orígenes autofirmados .Tener su propio servidor con el certificado adecuado es probablemente una exageración en su caso, ya que podría usar esta configuración en lugar de la máquina con certificado autofirmado, pero hay muchos servicios de proxy abiertos anónimos por ahí.
Entonces, dos enfoques que me vienen a la mente son:
.parentWindow
. Si su ventana recibió un mensaje, puede estar seguro de que el servidor está funcionando (o, más precisamente, estaba funcionando una fracción de segundo antes).Si solo está interesado en su entorno local, puede intentar ejecutar Chrome con
--disable-web-security
flag.Otra sugerencia: ¿intentó cargar una imagen mediante programación para averiguar si hay más información allí?
fuente
Echa un vistazo a jQuery.ajaxError () Referencia tomada de: jQuery AJAX Error Handling (códigos de estado HTTP) Detecta errores globales de Ajax que puedes manejar de varias formas a través de HTTP o HTTPS:
fuente
Desafortunadamente, la API XHR del navegador actual no proporciona una indicación explícita de cuándo el navegador se niega a conectarse debido a una "respuesta insegura", y también cuando no confía en el certificado HTTP / SSL del sitio web.
Pero hay formas de solucionar este problema.
Una solución que se me ocurrió para determinar cuándo el navegador no confía en el certificado HTTP / SSL es detectar primero si se ha producido un error XHR (usando la
error()
devolución de llamada jQuery, por ejemplo), luego verificar si la llamada XHR es a un 'https : // 'URL, y luego verifique si el XHRreadyState
es 0, lo que significa que la conexión XHR ni siquiera se ha abierto (que es lo que sucede cuando al navegador no le gusta el certificado).Aquí está el código donde hago esto: https://github.com/maratbn/RainbowPayPress/blob/e9e9472a36ced747a0f9e5ca9fa7d96959aeaf8a/rainbowpaypress/js/le_requirejs/public/model_info__transaction_details.js#L88
fuente
No creo que actualmente haya una forma de detectar estos mensajes de error, pero un truco que puede hacer es usar un servidor como nginx frente a su servidor de aplicaciones, de modo que si el servidor de aplicaciones no funciona, obtendrá un error error de puerta de enlace de nginx con
502
código de estado que puede detectar en JS. De lo contrario, si el certificado no es válido, seguirá recibiendo el mismo error genérico constatusCode = 0
.fuente