Skip to content

Commit 92ca51f

Browse files
authored
Merge pull request #2 from gemini-testing/dd.correct_close_connection
fix: listen close event from client and server
2 parents cb1ce77 + 003a07e commit 92ca51f

File tree

3 files changed

+40
-36
lines changed

3 files changed

+40
-36
lines changed

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,27 +395,28 @@ proxyServer.listen(8015);
395395
396396
};
397397
```
398-
* **wsInterceptServerMsg**: Is a handler which is called when a websocket message is intercepted on its way to the server. It takes two arguments: `data` - is a websocket message and flags (fin, mask, compress, binary). If falsy value is returned then nothing will be sended to the target server.
399-
```
398+
* **wsInterceptClientMsg**: Is a handler which is called when a websocket message is intercepted on its way to the server from the client. It takes two arguments: `data` - is a websocket message and flags (fin, mask, compress, binary). If falsy value is returned then nothing will be sended to the client.
399+
```
400400
const proxy = new HttpProxy({
401401
...
402-
wsInterceptServerMsg: (data, flags) {
402+
wsInterceptClientMsg: (data, flags) {
403403
return typeof data === 'string ? data.toUpperCase() : data;
404404
}
405405
...
406406
})
407407
```
408-
* **wsInterceptClientMsg**: Is a handler which is called when a websocket message is intercepted on its way to the client. It takes two arguments: `data` - is a websocket message and flags (fin, mask, compress, binary). If falsy value is returned then nothing will be sended to the client.
409-
```
408+
* **wsInterceptServerMsg**: Is a handler which is called when a websocket message is intercepted on its way to the client from the server. It takes two arguments: `data` - is a websocket message and flags (fin, mask, compress, binary). If falsy value is returned then nothing will be sended to the target server.
409+
```
410410
const proxy = new HttpProxy({
411411
...
412-
wsInterceptClientMsg: (data, flags) {
412+
wsInterceptServerMsg: (data, flags) {
413413
return typeof data === 'string ? data.toUpperCase() : data;
414414
}
415415
...
416416
})
417417
```
418418
419+
419420
**NOTE:**
420421
`options.ws` and `options.ssl` are optional.
421422
`options.target` and `options.forward` cannot both be missing
@@ -434,8 +435,8 @@ If you are using the `proxyServer.listen` method, the following options are also
434435
* `proxyReq`: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "web" connections
435436
* `proxyReqWs`: This event is emitted before the data is sent. It gives you a chance to alter the proxyReq request object. Applies to "websocket" connections
436437
* `proxyRes`: This event is emitted if the request to the target got a response.
437-
* `wsServerMsg`: This event is emitted after websocket message is sended to the server.
438-
* `wsClientMsg`: This event is emitted after webscoket mesage is sended to the client.
438+
* `wsClientMsg`: This event is emitted after webscoket mesage is sended from the client to the server.
439+
* `wsServerMsg`: This event is emitted after websocket message is sended from the server to the client.
439440
* `open`: This event is emitted once the proxy websocket was created and piped into the target websocket.
440441
* `close`: This event is emitted once the proxy websocket was closed.
441442
* (DEPRECATED) `proxySocket`: Deprecated in favor of `open`.

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,8 @@ module.exports = {
145145
//
146146
socket.write(createHttpHeader('HTTP/1.1 101 Switching Protocols', proxyRes.headers));
147147

148-
if (options.wsInterceptServerMsg || options.wsInterceptClientMsg) {
149-
WsInterceptor.create({socket, options, proxyReq, proxyRes, proxySocket}).intercept();
150-
}
151-
else {
152-
proxySocket.pipe(socket).pipe(proxySocket);
153-
}
148+
const wsInterceptor = WsInterceptor.create({socket, options, proxyReq, proxyRes, proxySocket});
149+
wsInterceptor.startDataTransfer();
154150

155151
server.emit('open', proxySocket);
156152
server.emit('proxySocket', proxySocket); //DEPRECATED.

lib/http-proxy/ws/interceptor.js

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ const Extensions = require('ws/lib/Extensions');
55
const Receiver = require('ws/lib/Receiver');
66
const Sender = require('ws/lib/Sender');
77

8-
const acceptExtensions = ({extenstions, isServer}) => {
8+
const acceptExtensions = ({extensions, isServer}) => {
99
const {extensionName} = PerMessageDeflate;
10-
const extenstion = extenstions[extensionName];
10+
const extension = extensions[extensionName];
1111

12-
if (!extenstion) {
12+
if (!extension) {
1313
return {};
1414
}
1515

1616
const perMessageDeflate = new PerMessageDeflate({}, isServer);
17-
perMessageDeflate.accept(extenstion);
17+
perMessageDeflate.accept(extension);
1818

1919
return {[extensionName]: perMessageDeflate};
2020
};
@@ -46,18 +46,23 @@ module.exports = class Interceptor {
4646
this._proxyReq = proxyReq;
4747
this._proxyRes = proxyRes;
4848
this._proxySocket = proxySocket;
49+
this._isSocketOpened = true;
4950

5051
this._configure();
5152
}
5253

5354
_configure() {
55+
this._proxySocket.on('close', () => {
56+
this._isSocketOpened = false;
57+
});
58+
5459
const secWsExtensions = this._proxyRes.headers['sec-websocket-extensions'];
55-
const extenstions = Extensions.parse(secWsExtensions);
56-
this._isCompressed = secWsExtensions && secWsExtensions.indexOf('permessage-deflate') != -1;
60+
const extensions = Extensions.parse(secWsExtensions);
61+
this._isCompressed = secWsExtensions && secWsExtensions.includes('permessage-deflate');
5762

5863
// need both versions of extensions for each side of the proxy connection
59-
this._clientExtenstions = this._isCompressed ? acceptExtensions({extenstions, isServer: false}) : null;
60-
this._serverExtenstions = this._isCompressed ? acceptExtensions({extenstions, isServer: true}) : null;
64+
this._clientExtensions = this._isCompressed ? acceptExtensions({extensions, isServer: false}) : null;
65+
this._serverExtensions = this._isCompressed ? acceptExtensions({extensions, isServer: true}) : null;
6166
}
6267

6368
_getDataSender({sender, event, options}) {
@@ -69,35 +74,37 @@ module.exports = class Interceptor {
6974
};
7075
}
7176

72-
_interceptServerMessages() {
73-
const receiver = new Receiver(this._clientExtenstions);
74-
const sender = new Sender(this._proxySocket, this._serverExtenstions);
77+
_interceptClientMessages() {
78+
const receiver = new Receiver(this._clientExtensions);
79+
const sender = new Sender(this._proxySocket, this._serverExtensions);
7580

7681
// frame must be masked when send from client to server - https://tools.ietf.org/html/rfc6455#section-5.3
7782
const options = {mask: true};
78-
const dataSender = this._getDataSender({sender, event: 'wsServerMsg', options});
83+
const dataSender = this._getDataSender({sender, event: 'wsClientMsg', options});
7984

80-
receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: false});
81-
receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: true});
85+
receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: false});
86+
receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: true});
87+
receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask);
8288

8389
this._socket.on('data', (data) => receiver.add(data));
8490
}
8591

86-
_interceptClientMessages() {
87-
const receiver = new Receiver(this._serverExtenstions);
88-
const sender = new Sender(this._socket, this._clientExtenstions);
92+
_interceptServerMessages() {
93+
const receiver = new Receiver(this._serverExtensions);
94+
const sender = new Sender(this._socket, this._clientExtensions);
8995

9096
const options = {mask: false};
91-
const dataSender = this._getDataSender({sender, event: 'wsClientMsg', options});
97+
const dataSender = this._getDataSender({sender, event: 'wsServerMsg', options});
9298

93-
receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: false});
94-
receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptClientMsg, dataSender, binary: true});
99+
receiver.ontext = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: false});
100+
receiver.onbinary = getMsgHandler({interceptor: this._options.wsInterceptServerMsg, dataSender, binary: true});
101+
receiver.onclose = (code, msg, {masked: mask}) => this._isSocketOpened && sender.close(code, msg, mask);
95102

96103
this._proxySocket.on('data', (data) => receiver.add(data));
97104
}
98105

99-
intercept() {
100-
this._interceptServerMessages();
106+
startDataTransfer() {
101107
this._interceptClientMessages();
108+
this._interceptServerMessages();
102109
}
103110
};

0 commit comments

Comments
 (0)