obtenir la raison pour laquelle les Websockets se ferment avec le code de fermeture 1006

92

Je voudrais obtenir la raison de la fermeture des websockets, afin que je puisse montrer le bon message à l'utilisateur.

j'ai

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

Le code est toujours 1006 et la raison est toujours "". Mais je veux distinguer différentes raisons de clôture.

Par exemple, la ligne de commande donne une raison d'erreur: "vous ne pouvez pas supprimer cela, car la base de données ne vous le permettra pas". Mais sur la console de Chrome, la raison est toujours "".

Une autre façon de distinguer les différentes raisons de clôture?

slevin
la source
Je pense que c'est à cause de la façon dont le serveur gère les événements connectés / déconnectés. Je ne peux pas le dire avec certitude, mais la fermeture de la connexion doit être gérée correctement sur le serveur également avec du code. Essayez de remplacer les méthodes intégrées On Connected / Disconnected sur le serveur et voyez. Je suppose seulement que vous le fermez mais que le serveur ne se ferme pas correctement et ne transmet donc pas la bonne réponse fermée.
Michael Puckett II

Réponses:

124

Fermer le code 1006 est un code spécial qui signifie que la connexion a été fermée anormalement (localement) par l'implémentation du navigateur.

Si votre navigateur client signale un code de fermeture 1006, alors vous devriez regarder l' websocket.onerror(evt)événement pour plus de détails.

Cependant, Chrome signalera rarement les 1006raisons du code de fermeture du côté Javascript. Cela est probablement dû aux règles de sécurité du client dans la spécification WebSocket pour empêcher toute utilisation abusive de WebSocket. (comme son utilisation pour rechercher des ports ouverts sur un serveur de destination ou pour générer de nombreuses connexions pour une attaque par déni de service).

Notez que Chrome signalera souvent un code de fermeture en 1006cas d'erreur lors de la mise à niveau HTTP vers Websocket (il s'agit de l'étape avant qu'un WebSocket ne soit techniquement «connecté»). Pour des raisons telles qu'une mauvaise authentification ou autorisation, ou une mauvaise utilisation du protocole (comme la demande d'un sous-protocole, mais le serveur lui-même ne prend pas en charge ce même sous-protocole), ou même une tentative de communication avec un emplacement de serveur qui n'est pas un WebSocket ( comme tenter de se connecter àws://images.google.com/ )

Fondamentalement, si vous voyez un code de fermeture 1006, vous avez une erreur de très bas niveau avec WebSocket lui-même (similaire à "Impossible d'ouvrir le fichier" ou "Erreur de socket"), pas vraiment destinée à l'utilisateur, car elle indique un problème de bas niveau avec votre code et votre implémentation. Résolvez vos problèmes de bas niveau, puis lorsque vous êtes connecté, vous pouvez alors inclure des codes d'erreur plus raisonnables. Vous pouvez accomplir cela en termes de portée ou de gravité dans votre projet. Exemple: les informations et le niveau d'avertissement font partie du protocole spécifique de votre projet et ne provoquent pas l'arrêt de la connexion. Avec des messages graves ou fatals, les rapports utilisent également le protocole de votre projet pour transmettre autant de détails que vous le souhaitez, puis la fermeture de la connexion en utilisant les capacités limitées du flux de fermeture WebSocket.

Sachez que les codes de fermeture de WebSocket sont très strictement définis et que la phrase / le message de raison de fermeture ne peut pas dépasser 123 caractères (il s'agit d'une limitation intentionnelle de WebSocket).

Mais tout n'est pas perdu, si vous ne voulez que ces informations pour des raisons de débogage, le détail de la fermeture et sa raison sous-jacente sont souvent signalés avec beaucoup de détails dans la console Javascript de Chrome.

Joakim Erdfelt
la source
4
Joakim, merci, réponse très détaillée. Si j'utilise sok.onerror=function (evt) {console.log(evt);}les détails ne sont pas tellement. Pas même un reasonou quelque chose. Alors, pas d'options du tout? Je viens de montrer à l'utilisateur, something is wrong, or not connencted?pas si convivial, ce serait bien si l'utilisateur peut voir "Vous ne pouvez pas supprimer, cause des restrictions de base de données". Des options? Merci
slevin
Vous devriez utiliser à la sok.oncloseplace quels déclencheurs close event, il a reasonet codededans
Ihab Khattab
@IhabKhattab qui serait spécifique au code de fermeture, et aussi lorsque la fermeture se produit. avoir sok.onclosefonctionnera pour de nombreux chemins, mais pas pour tous les chemins. Protocole particulièrement mauvais, mauvaises erreurs de prise de contact (comme certaines conditions qui pourraient provoquer un code de fermeture 1006). Cela changera-t-il à l'avenir? Probablement. Mais quand cette réponse a été écrite, c'était vrai.
Joakim Erdfelt
@JoakimErd s'est senti désolé, je répondais à la question de @slevin à propos de son absence de reasonretour quand il a utilisé, onerrorje signalais que ces propriétés codeet reasonspécifiques à l' closeévénement et non à l' errorévénement. il vaudrait donc mieux qu'il l' utilise à la oncloseplace, est-ce que je manque quelque chose?
Ihab Khattab
@IhabKhattab oui, car sa question était spécifique sur le code d'erreur 1006qui a une signification particulière, et une gestion spéciale dans la spécification websocket et l'api javascript websocket. La chaîne / le message de raison dans certaines 1006conditions n'est spécifiquement et intentionnellement exposé nulle part dans l'API. (comme la réponse l'a souligné). Ce n'est pas un bogue dans l'API, il répond simplement aux diverses spécifications et à leurs préoccupations concernant l'utilisation abusive de websocket à des fins non-websocket.
Joakim Erdfelt
16

Dans mon cas et peut-être @BIOHAZARD, c'était le cas nginx proxy timeout. Par défaut, c'est 60sec sans activité dans le socket

Je l'ai changé en 24h nginxet le problème a été résolu

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
MixerOID
la source
Merci pour cela! C'est la raison de l'erreur 1006 dans mon cas.
Steve Hanov
11

Il semble que ce soit le cas lorsque Chrome n'est pas conforme à la norme WebSocket. Lorsque le serveur lance la fermeture et envoie une trame de fermeture à un client, Chrome considère qu'il s'agit d'une erreur et la signale au côté JS avec le code 1006 et aucun message de raison. Dans mes tests, Chrome ne répond jamais aux cadres de fermeture déclenchés par le serveur (code de fermeture 1000), ce qui suggère que le code 1006 signifie probablement que Chrome signale sa propre erreur interne.

PS Firefox v57.00 gère ce cas correctement et envoie avec succès le message de raison du serveur au côté JS.

utilisateur10663464
la source
3

J'ai pensé que cela pourrait être utile pour les autres. Connaître les regex est utile, les enfants. Rester à l'école.

Edit: Je l'ai transformé en une fonction dandy pratique!

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)';
}

Usage:

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'
}

Source (avec des modifications mineures pour la concision): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes

Andrew
la source
1

J'ai l'erreur en utilisant Chrome comme client et golang gorilla websocket comme serveur sous proxy nginx

Et envoyer juste un message "ping" du serveur au client toutes les x secondes problème résolu

DANGER BIOLOGIQUE
la source
0

Il se peut que l'URL de votre websocket que vous utilisez dans l'appareil ne soit pas la même (vous rencontrez une URL de websocket différente à partir d'android / iphonedevice)

Ankush Sahu
la source