Skip to content

Commit 502711a

Browse files
authored
Merge pull request #6 from gemini-testing/dd.support_allow_half_open_socket
fix: correctly close half-opened socket
2 parents e9ef418 + b1247c6 commit 502711a

File tree

2 files changed

+17
-11
lines changed

2 files changed

+17
-11
lines changed

lib/http-proxy/passes/ws-incoming.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,13 @@ module.exports = {
131131
// The pipe below will end proxySocket if socket closes cleanly, but not
132132
// if it errors (eg, vanishes from the net and starts returning
133133
// EHOSTUNREACH). We need to do that explicitly.
134-
socket.on('error', function () {
134+
socket.on('error', function (err) {
135+
console.error('ERROR: socket closed with:', err);
135136
proxySocket.end();
136137
});
137138

139+
socket.on('end', () => socket.end());
140+
138141
common.setupSocket(proxySocket);
139142

140143
if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);

lib/http-proxy/ws/interceptor.js

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ module.exports = class Interceptor {
3131
this._proxyReq = proxyReq;
3232
this._proxyRes = proxyRes;
3333
this._proxySocket = proxySocket;
34-
this._isSocketOpened = true;
34+
this._isClientSocketOpen = true;
35+
this._isServerSocketOpen = true;
3536

3637
this._configure();
3738
}
3839

3940
_configure() {
40-
this._proxySocket.on('close', () => {
41-
this._isSocketOpened = false;
42-
});
41+
this._proxySocket.on('close', () => this._isClientSocketOpen = false);
42+
this._socket.on('close', () => this._isServerSocketOpen = false);
4343

4444
const secWsExtensions = this._proxyRes.headers['sec-websocket-extensions'];
4545
const extensions = Extensions.parse(secWsExtensions);
@@ -50,10 +50,11 @@ module.exports = class Interceptor {
5050
this._serverExtensions = this._isCompressed ? acceptExtensions({extensions, isServer: true}) : null;
5151
}
5252

53-
_getDataSender({sender, event, options}) {
53+
_getDataSender({sender, dataSendCond, event, options}) {
5454
return ({data, binary = false}) => {
5555
const opts = Object.assign({fin: true, compress: this._isCompressed, binary}, options);
56-
sender.send(data, opts);
56+
57+
dataSendCond() && sender.send(data, opts);
5758

5859
this._proxyReq.emit(event, {data, binary});
5960
};
@@ -82,11 +83,12 @@ module.exports = class Interceptor {
8283

8384
// frame must be masked when send from client to server - https://tools.ietf.org/html/rfc6455#section-5.3
8485
const options = {mask: true};
85-
const dataSender = this._getDataSender({sender, event: 'wsClientMsg', options});
86+
const dataSendCond = () => this._isClientSocketOpen;
87+
const dataSender = this._getDataSender({sender, dataSendCond, event: 'wsClientMsg', options});
8688

8789
receiver.ontext = this._getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: false});
8890
receiver.onbinary = this._getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: true});
89-
receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask);
91+
receiver.onclose = (code, msg, {masked: mask}) => this._isClientSocketOpen && sender.close(code, msg, mask);
9092

9193
this._socket.on('data', (data) => receiver.add(data));
9294
}
@@ -97,11 +99,12 @@ module.exports = class Interceptor {
9799
this._proxyReq.emit('serverSenderInited', sender);
98100

99101
const options = {mask: false};
100-
const dataSender = this._getDataSender({sender, event: 'wsServerMsg', options});
102+
const dataSendCond = () => this._isServerSocketOpen;
103+
const dataSender = this._getDataSender({sender, dataSendCond, event: 'wsServerMsg', options});
101104

102105
receiver.ontext = this._getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: false});
103106
receiver.onbinary = this._getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: true});
104-
receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask);
107+
receiver.onclose = (code, msg, {masked: mask}) => this._isServerSocketOpen && sender.close(code, msg, mask);
105108

106109
this._proxySocket.on('data', (data) => receiver.add(data));
107110
}

0 commit comments

Comments
 (0)