diff --git a/src/component/internal/reconnector/websocket.ts b/src/component/internal/reconnector/websocket.ts index 73970852..6822a960 100644 --- a/src/component/internal/reconnector/websocket.ts +++ b/src/component/internal/reconnector/websocket.ts @@ -30,7 +30,7 @@ export class WebsocketReconnector extends ReconnectorAbstract { if (!this._websocket.supported) return if (this._websocket.connected) { - this._websocket.disconnect() + this._websocket.disconnect('connection replaced') } let url = this._state.url @@ -45,7 +45,7 @@ export class WebsocketReconnector extends ReconnectorAbstract { } public disconnect() { - this._websocket.disconnect() + this._websocket.disconnect('manual disconnect') } public destroy() { diff --git a/src/component/internal/websocket.ts b/src/component/internal/websocket.ts index 181cd8bd..1872c599 100644 --- a/src/component/internal/websocket.ts +++ b/src/component/internal/websocket.ts @@ -8,6 +8,25 @@ export interface NekoWebSocketEvents { message: (event: string, payload: any) => void } +const statusCodeMap = { + 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', +} as Record + export class NekoWebSocket extends EventEmitter { private _ws?: WebSocket @@ -37,7 +56,7 @@ export class NekoWebSocket extends EventEmitter { if (typeof this._ws !== 'undefined') { this._log.debug(`previous websocket connection needs to be closed`) - this.disconnect() + this.disconnect('connection replaced') } this._ws = new WebSocket(url) @@ -45,12 +64,20 @@ export class NekoWebSocket extends EventEmitter { this._log.info(`connecting`) this._ws.onopen = this.onConnected.bind(this) - this._ws.onclose = this.onDisconnected.bind(this, 'close') + this._ws.onclose = (e: CloseEvent) => { + let reason = 'close' + + if (e.code in statusCodeMap) { + reason = statusCodeMap[e.code] + } + + this.onDisconnected(reason) + } this._ws.onerror = this.onDisconnected.bind(this, 'error') this._ws.onmessage = this.onMessage.bind(this) } - public disconnect() { + public disconnect(reason: string) { if (typeof this._ws !== 'undefined') { // unmount all events this._ws.onopen = () => {} @@ -59,7 +86,7 @@ export class NekoWebSocket extends EventEmitter { this._ws.onmessage = () => {} try { - this._ws.close() + this._ws.close(1000, reason) } catch {} this._ws = undefined @@ -94,7 +121,7 @@ export class NekoWebSocket extends EventEmitter { } private onDisconnected(reason: string) { - this.disconnect() + this.disconnect(reason) this._log.info(`disconnected`, { reason }) this.emit('disconnected', new Error(`connection ${reason}`))