Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,26 @@ data.
});
proxy.web(req, res, option);

```


#### Modify websockets' proxy request with asynchronous handler

If you want to modify a websockets request with asynchronous hadnler, `proxyReqWs` provides special callback argument named `asyncContext` which gets a single async callback that can return a promise.
The request would be proxied once the promise is resolved.

```js

onProxyReqWs: (proxyReq, req, socket, options, head, asyncContext) =>
asyncContext(async () => {
// code ...
const result = await anyAsyncOperation()
// code ...
proxyReq.setHeader('key', result)
}),

```


#### ProxyTable API

Expand Down
23 changes: 18 additions & 5 deletions lib/http-proxy/passes/ws-incoming.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module.exports = {
*
* @api private
*/
stream : function stream(req, socket, options, head, server, clb) {
stream : async function stream(req, socket, options, head, server, clb) {

var createHttpHeader = function(line, headers) {
return Object.keys(headers).reduce(function (head, key) {
Expand Down Expand Up @@ -104,9 +104,7 @@ module.exports = {
common.setupOutgoing(options.ssl || {}, options, req)
);

// Enable developers to modify the proxyReq before headers are sent
if (server) { server.emit('proxyReqWs', proxyReq, req, socket, options, head); }

// It is important to register the event listeners of proxyReq before the first await, so we don't have small period of time in which we lose emitted events
// Error Handler
proxyReq.on('error', onOutgoingError);
proxyReq.on('response', function (res) {
Expand Down Expand Up @@ -147,8 +145,23 @@ module.exports = {
server.emit('open', proxySocket);
server.emit('proxySocket', proxySocket); //DEPRECATED.
});

// Enable developers to modify the proxyReq before headers are sent
if (server) {
// Provides a way for the event handler to communicate back to the emitter when it finishes its async handling
let asyncHandler
const asyncContext = (callback) => {
asyncHandler = callback
}

return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT
server.emit('proxyReqWs', proxyReq, req, socket, options, head, asyncContext);

if (asyncHandler) {
await asyncHandler()
}
}

proxyReq.end();

function onOutgoingError(err) {
if (clb) {
Expand Down
45 changes: 45 additions & 0 deletions test/lib-http-proxy-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,51 @@ describe('lib/http-proxy.js', function() {
});
});

it('should detect a proxyReq event and modify headers with async handler', function (done) {
var ports = { source: gen.port, proxy: gen.port },
proxy,
proxyServer,
destiny;

proxy = httpProxy.createProxyServer({
target: 'ws://127.0.0.1:' + ports.source,
ws: true
});

proxy.on('proxyReqWs', function(proxyReq, req, socket, options, head, asyncContext) {
asyncContext(async function() {
proxyReq.setHeader('X-Special-Proxy-Header', 'async-foobar');
});
});

proxyServer = proxy.listen(ports.proxy);

destiny = new ws.Server({ port: ports.source }, function () {
var client = new ws('ws://127.0.0.1:' + ports.proxy);

client.on('open', function () {
client.send('hello there');
});

client.on('message', function (msg) {
expect(msg).to.be('Hello over websockets');
client.close();
proxyServer.close();
destiny.close();
done();
});
});

destiny.on('connection', function (socket, upgradeReq) {
expect(upgradeReq.headers['x-special-proxy-header']).to.eql('async-foobar');

socket.on('message', function (msg) {
expect(msg).to.be('hello there');
socket.send('Hello over websockets');
});
});
});

it('should forward frames with single frame payload (including on node 4.x)', function (done) {
var payload = Array(65529).join('0');
var ports = { source: gen.port, proxy: gen.port };
Expand Down