Skip to content

Commit dc1f191

Browse files
committed
fix: abort upgrade on edge case where socket closed early
1 parent 559040e commit dc1f191

File tree

1 file changed

+32
-21
lines changed

1 file changed

+32
-21
lines changed

lib/server.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,21 @@ class RPCServer extends EventEmitter {
110110
}
111111
};
112112

113+
socket.on('error', (err) => {
114+
abortUpgrade(err);
115+
});
116+
113117
try {
114118
if (this._state !== OPEN) {
115119
throw new WebsocketUpgradeError(500, "Server not open");
116120
}
117121

118-
const headers = request.headers;
122+
if (socket.readyState !== 'open') {
123+
throw new WebsocketUpgradeError(400, `Client readyState = '${socket.readyState}'`);
124+
}
119125

126+
const headers = request.headers;
127+
120128
if (headers.upgrade.toLowerCase() !== 'websocket') {
121129
throw new WebsocketUpgradeError(400, "Can only upgrade websocket upgrade requests");
122130
}
@@ -163,25 +171,32 @@ class RPCServer extends EventEmitter {
163171
const accept = (session, protocol) => {
164172
if (resolved) return;
165173
resolved = true;
174+
175+
try {
176+
if (socket.readyState !== 'open') {
177+
throw new WebsocketUpgradeError(400, `Client readyState = '${socket.readyState}'`);
178+
}
166179

167-
if (protocol === undefined) {
168-
// pick first subprotocol (preferred by server) that is also supported by the client
169-
protocol = (this._options.protocols ?? []).find(p => protocols.has(p));
170-
} else if (protocol !== false && !protocols.has(protocol)) {
171-
abortUpgrade(new WebsocketUpgradeError(400, `Client doesn't support expected subprotocol`));
172-
return;
173-
}
180+
if (protocol === undefined) {
181+
// pick first subprotocol (preferred by server) that is also supported by the client
182+
protocol = (this._options.protocols ?? []).find(p => protocols.has(p));
183+
} else if (protocol !== false && !protocols.has(protocol)) {
184+
throw new WebsocketUpgradeError(400, `Client doesn't support expected subprotocol`);
185+
}
174186

175-
// cache auth results for connection creation
176-
this._pendingUpgrades.set(request, {
177-
session: session ?? {},
178-
protocol,
179-
handshake
180-
});
187+
// cache auth results for connection creation
188+
this._pendingUpgrades.set(request, {
189+
session: session ?? {},
190+
protocol,
191+
handshake
192+
});
181193

182-
this._wss.handleUpgrade(request, socket, head, ws => {
183-
this._wss.emit('connection', ws, request);
184-
});
194+
this._wss.handleUpgrade(request, socket, head, ws => {
195+
this._wss.emit('connection', ws, request);
196+
});
197+
} catch (err) {
198+
abortUpgrade(err);
199+
}
185200
};
186201

187202
const reject = (code = 404, message = 'Not found') => {
@@ -198,10 +213,6 @@ class RPCServer extends EventEmitter {
198213
reject(400, `Client connection closed before upgrade complete`);
199214
});
200215

201-
socket.on('error', (err) => {
202-
abortUpgrade(err);
203-
});
204-
205216
if (this.authCallback) {
206217
await this.authCallback(
207218
accept,

0 commit comments

Comments
 (0)