Skip to content

Commit 6cfd0f3

Browse files
committed
Merge pull request #49 from chimurai/proxyTable-does-not-work-for-websocket-connections
feat(proxyTable): add proxyTable support for ws
2 parents fe24b97 + bb28503 commit 6cfd0f3

File tree

3 files changed

+75
-21
lines changed

3 files changed

+75
-21
lines changed

examples/websocket/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ <h2>WebSocket demo</h2>
2929
<fieldset id="configuration">
3030
<p>
3131
<label for="location">location:</label>
32-
<input id="location" type="text" disabled="disabled" value="ws://localhost:3000">
32+
<input id="location" type="text" value="ws://localhost:3000">
3333
<button id="connect">connect</button>
3434
<button id="disconnect" disabled="disabled">disconnect</button>
3535
</p>
@@ -66,7 +66,7 @@ <h2>WebSocket demo</h2>
6666
disconnect.disabled = false;
6767
messaging.disabled = false;
6868

69-
socket = new WebSocket('ws://localhost:3000');
69+
socket = new WebSocket(location.value);
7070
socket.onopen = function () { log('CONNECTED'); };
7171
socket.onclose = function () { log('DISCONNECTED'); };
7272
socket.onerror = function () { log('SOCKET ERROR OCCURED'); };

index.js

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,10 @@ var httpProxyMiddleware = function (context, opts) {
5858
if (contextMatcher.match(config.context, req.url)) {
5959
logger.debug('[HPM] Context match: "%s" -> "%s"', config.context, req.url);
6060

61-
// handle option.pathRewrite
62-
if (pathRewriter) {
63-
req.url = pathRewriter(req.url);
64-
}
65-
if (proxyOptions.proxyTable) {
66-
// change option.target when proxyTable present.
67-
var altOpts = ProxyTable.createProxyOptions(req, proxyOptions);
68-
logger.debug('[HPM] Proxying "%s": "%s" -> "%s"', req.url, req.hostname, altOpts.target);
69-
proxy.web(req, res, altOpts);
70-
} else {
71-
logger.debug('[HPM] Proxying "%s": "%s" -> "%s"', req.url, req.hostname, proxyOptions.target);
72-
proxy.web(req, res);
73-
}
61+
var activeProxyOptions = __prepareProxyRequest(req);
62+
63+
logger.debug('[HPM] Proxying "%s": "%s" -> "%s"', req.url, req.hostname, activeProxyOptions.target);
64+
proxy.web(req, res, activeProxyOptions);
7465

7566
} else {
7667
next();
@@ -93,14 +84,49 @@ var httpProxyMiddleware = function (context, opts) {
9384

9485
function handleUpgrade (req, socket, head) {
9586
if (contextMatcher.match(config.context, req.url)) {
96-
if (pathRewriter) {
97-
req.url = pathRewriter(req.url);
98-
}
99-
proxy.ws(req, socket, head);
87+
88+
var activeProxyOptions = __prepareProxyRequest(req);
89+
90+
proxy.ws(req, socket, head, activeProxyOptions);
10091
logger.info('[HPM] Upgrading to WebSocket');
10192
}
10293
}
10394

95+
/**
96+
* Apply option.proxyTable and option.pathRewrite
97+
* Order matters:
98+
ProxyTable uses original path for routing;
99+
NOT the modified path, after it has been rewritten by pathRewrite
100+
*/
101+
function __prepareProxyRequest(req) {
102+
// apply option.proxyTable
103+
var alteredProxyOptions = __applyProxyTableOption(req, proxyOptions);
104+
105+
// apply option.pathRewrite
106+
__applyPathRewrite(req, pathRewriter);
107+
108+
return alteredProxyOptions;
109+
}
110+
111+
// Modify option.target when proxyTable present.
112+
// return altered options
113+
function __applyProxyTableOption (req) {
114+
var result = proxyOptions;
115+
116+
if (proxyOptions.proxyTable) {
117+
result = ProxyTable.createProxyOptions(req, proxyOptions);
118+
}
119+
120+
return result;
121+
}
122+
123+
// rewrite path
124+
function __applyPathRewrite (req) {
125+
if (pathRewriter) {
126+
req.url = pathRewriter(req.url);
127+
}
128+
}
129+
104130
function getProxyErrorHandler () {
105131
if (_.isFunction(proxyOptions.onError)) {
106132
return proxyOptions.onError; // custom error listener
@@ -111,7 +137,7 @@ var httpProxyMiddleware = function (context, opts) {
111137

112138
function proxyErrorLogger (err, req, res) {
113139
var hostname = (req.hostname || req.host) || (req.headers && req.headers.host) // (node0.10 || node 4/5) || (websocket)
114-
var targetUri = proxyOptions.target.host + req.url;
140+
var targetUri = (proxyOptions.target.host || proxyOptions.target) + req.url;
115141

116142
logger.error('[HPM] Proxy error: %s. %s -> "%s"', err.code, hostname, targetUri);
117143
}

test/websocket.spec.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,40 @@ describe('WebSocket proxy', function () {
106106
});
107107
});
108108

109+
describe('with proxyTable and pathRewrite', function () {
110+
111+
beforeEach(function () {
112+
proxyServer.close();
113+
// override
114+
proxy = proxyMiddleware('ws://notworkinghost:6789', {proxyTable: {'/socket': 'ws://localhost:8000'}, pathRewrite: {'^/socket' : ''}});
115+
proxyServer = createServer(3000, proxy);
116+
});
117+
118+
beforeEach(function (done) {
119+
proxyServer.on('upgrade', proxy.upgrade);
120+
121+
ws = new WebSocket('ws://localhost:3000/socket');
122+
123+
ws.on('message', function incoming(message) {
124+
responseMessage = message;
125+
done();
126+
});
127+
128+
ws.on('open', function open() {
129+
ws.send('foobar');
130+
});
131+
});
132+
133+
it('should proxy to path', function () {
134+
expect(responseMessage).to.equal('foobar');
135+
});
136+
});
137+
109138
afterEach(function () {
110139
proxyServer.close();
111140
wss.close();
112141
ws = null;
113142
});
114-
115143
});
116144

117145
function createServer (portNumber, middleware) {

0 commit comments

Comments
 (0)