obteniendo la razón por la que websockets se cerró con el código de cierre 1006

92

Me gustaría obtener la razón por la que se cerraron los websockets, para poder mostrar el mensaje correcto al usuario.

yo tengo

sok.onerror=function (evt) 
     {//since there is an error, sockets will close so...
       sok.onclose=function(e){
           console.log("WebSocket Error: " , e);}

El código es siempre 1006 y el motivo siempre es "". Pero quiero distinguir diferentes razones de cierre.

Por ejemplo, la línea de comando da una razón de error: "no puedes borrar eso, porque la base de datos no te lo permite". Pero en la consola de Chrome, la razón sigue siendo "".

¿Alguna otra forma de diferenciar las diferentes razones de cierre?

slevin
fuente
Creo que esto se debe a la forma en que el servidor maneja los eventos conectados / desconectados. No puedo decirlo con seguridad, pero el cierre de la conexión debe manejarse correctamente en el servidor también con código. Intente anular los métodos integrados On Connected / Disconnected en el servidor y vea. Solo mi suposición es que lo está cerrando pero el servidor no se cierra correctamente y, por lo tanto, no transmite la respuesta cerrada adecuada.
Michael Puckett II

Respuestas:

124

El código de cierre1006 es un código especial que significa que la implementación del navegador cerró la conexión de forma anormal (localmente).

Si el cliente de su navegador informa un código de cierre 1006, entonces debería estar mirando el websocket.onerror(evt)evento para obtener más detalles.

Sin embargo, Chrome rara vez informará sobre 1006razones de código cerrado al lado de Javascript. Es probable que esto se deba a las reglas de seguridad del cliente en la especificación de WebSocket para evitar el abuso de WebSocket. (como usarlo para buscar puertos abiertos en un servidor de destino o para generar muchas conexiones para un ataque de denegación de servicio).

Tenga en cuenta que Chrome a menudo informará un código de cierre 1006si hay un error durante la actualización HTTP a Websocket (este es el paso antes de que un WebSocket esté técnicamente "conectado"). Por razones como una autenticación o autorización incorrecta, o un uso incorrecto del protocolo (como solicitar un subprotocolo, pero el servidor en sí no admite ese mismo subprotocolo), o incluso un intento de hablar con una ubicación de servidor que no es un WebSocket ( como intentar conectarse a ws://images.google.com/)

Básicamente, si ve un código de cierre 1006, tiene un error de nivel muy bajo con el propio WebSocket (similar a "No se puede abrir el archivo" o "Error de socket"), que en realidad no está destinado al usuario, ya que apunta a un problema de nivel bajo. con su código e implementación. Solucione sus problemas de bajo nivel y, cuando esté conectado, podrá incluir códigos de error más razonables. Puede lograr esto en términos de alcance o severidad en su proyecto. Ejemplo: la información y el nivel de advertencia son parte del protocolo específico de su proyecto y no provocan la terminación de la conexión. Con informes de mensajes graves o fatales, también utilice el protocolo de su proyecto para transmitir tantos detalles como desee y luego cierre la conexión utilizando las capacidades limitadas del flujo de cierre de WebSocket.

Tenga en cuenta que los códigos de cierre de WebSocket están definidos de forma muy estricta, y la frase / mensaje de motivo de cierre no puede superar los 123 caracteres de longitud (esta es una limitación intencionada de WebSocket).

Pero no todo está perdido, si solo desea esta información por razones de depuración, el detalle del cierre y su razón subyacente a menudo se informa con una buena cantidad de detalles en la consola Javascript de Chrome.

Joakim Erdfelt
fuente
4
Joakim, gracias, respuesta muy detallada. Si utilizo sok.onerror=function (evt) {console.log(evt);}los detalles no son tanto. Ni siquiera una reasono algo. Entonces, ¿no hay opciones en absoluto? Solo le muestro al usuario, something is wrong, or not connencted?No tan fácil de usar, sería bueno si el usuario pudiera ver "No se puede eliminar, debido a restricciones en la base de datos". ¿Alguna opción? Gracias
slevin
En su sok.oncloselugar, debe usar qué desencadenadores close event, tiene reasony codeen él
Ihab Khattab
@IhabKhattab que sería específico del código de cierre, y también cuando se produce el cierre. tener sok.onclosefuncionará para muchos caminos, pero no para todos. Especialmente mal protocolo, errores de apretón de manos incorrectos (como algunas condiciones que podrían causar código de cierre 1006). ¿Cambiará esto en el futuro? Probablemente. Pero cuando se escribió esta respuesta, era verdad.
Joakim Erdfelt
@JoakimErdfelt siento, estaba respondiendo a una pregunta sobre @slevin que no ha reasonregresado cuando usó onerrorMe estaba señalando que estas propiedades codey reasonespecífica a closeevento no errorevento. así que sería mejor para él usar oncloseen su lugar, ¿me estoy perdiendo algo?
Ihab Khattab
@IhabKhattab sí, ya que su pregunta era específica sobre el código de error 1006que tiene un significado especial y un manejo especial en la especificación websocket y la api websocket javascript. La razón por la que la cadena / mensaje en algunas 1006condiciones no se expone de manera específica e intencional en ninguna parte de la API. (como señaló la respuesta). Esto no es un error en la API, se trata simplemente de abordar las diversas especificaciones y sus preocupaciones sobre el abuso de websocket para fines que no sean de websocket.
Joakim Erdfelt
16

En mi caso, y posiblemente en el de @BIOHAZARD, lo fue nginx proxy timeout. De forma predeterminada, es un 60segundo sin actividad en el socket

Lo cambié a 24 horas nginxy resolvió el problema.

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
MixerOID
fuente
¡Gracias por esto! Es la razón del error 1006 en mi caso.
Steve Hanov
11

Parece que este es el caso cuando Chrome no cumple con el estándar WebSocket. Cuando el servidor inicia el cierre y envía un marco de cierre a un cliente, Chrome considera que esto es un error y lo informa al lado de JS con el código 1006 y sin mensaje de motivo. En mis pruebas, Chrome nunca responde a los marcos cerrados iniciados por el servidor (código de cierre 1000), lo que sugiere que el código 1006 probablemente significa que Chrome está informando su propio error interno.

PS Firefox v57.00 maneja este caso correctamente y entrega con éxito el mensaje del motivo del servidor al lado de JS.

usuario10663464
fuente
3

Pensé que esto podría ser útil para otros. Saber que la expresión regular es útil, niños. Permanece en la escuela.

Editar: ¡Lo convirtió en una función práctica y elegante!

let specificStatusCodeMappings = {
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Unused)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(For WebSocket standard)';
        } else if (code <= 2999) {
            return '(For WebSocket extensions)';
        } else if (code <= 3999) {
            return '(For libraries and frameworks)';
        } else if (code <= 4999) {
            return '(For applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Unknown)';
}

Uso:

getStatusCodeString(1006); //'Abnormal Closure'

{
    '0-999': '(Unused)',
    '1016-1999': '(For WebSocket standard)',
    '2000-2999': '(For WebSocket extensions)',
    '3000-3999': '(For libraries and frameworks)',
    '4000-4999': '(For applications)'
}

{
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
}

Fuente (con ediciones menores para la concisión): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes

Andrés
fuente
1

Tengo el error al usar Chrome como cliente y golang gorilla websocket como servidor bajo el proxy nginx

Y enviar un mensaje de "ping" del servidor al cliente cada x segundo problema resuelto

BIOPELIGRO
fuente
0

Esta puede ser la URL de su websocket que está utilizando en el dispositivo que no es la misma (está presionando una URL de websocket diferente desde el dispositivo android / iphone)

Ankush Sahu
fuente