Skip to content

Commit b0b0183

Browse files
committed
[api] Update WebSocket support to use http.Agent APIs
1 parent 5681fc1 commit b0b0183

File tree

1 file changed

+96
-122
lines changed

1 file changed

+96
-122
lines changed

lib/node-http-proxy.js

+96-122
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ exports.createServer = function () {
136136
server.on('upgrade', function(req, socket, head) {
137137
// Tunnel websocket requests too
138138

139-
proxy.proxyWebSocketRequest(port, host);
139+
proxy.proxyWebSocketRequest(req, socket, head, port, host);
140140
});
141141
}
142142

@@ -444,91 +444,111 @@ HttpProxy.prototype._forwardRequest = function (req) {
444444
});
445445
};
446446

447-
HttpProxy.prototype.proxyWebSocketRequest = function (port, server, host, data) {
448-
var self = this, req = self.req, socket = self.sock, head = self.head,
449-
headers = new _headers(req.headers), CRLF = '\r\n';
450-
451-
// Will generate clone of headers
452-
// To not change original
453-
function _headers(headers) {
454-
var h = {};
455-
for (var i in headers) {
456-
h[i] = headers[i];
457-
}
458-
return h;
459-
}
447+
HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, port, host, buffer) {
448+
var self = this, CRLF = '\r\n';
460449

461450
// WebSocket requests has method = GET
462-
if (req.method !== 'GET' || headers.upgrade.toLowerCase() !== 'websocket') {
451+
if (req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket') {
463452
// This request is not WebSocket request
464453
return;
465454
}
466455

467456
// Turn of all bufferings
468457
// For server set KeepAlive
469458
// For client set encoding
470-
function _socket(socket, server) {
459+
function _socket(socket, keepAlive) {
471460
socket.setTimeout(0);
472461
socket.setNoDelay(true);
473-
if (server) {
462+
if (keepAlive) {
474463
socket.setKeepAlive(true, 0);
475464
}
476465
else {
477466
socket.setEncoding('utf8');
478467
}
479468
}
469+
470+
function onUpgrade(reverseProxy) {
471+
var listeners = {};
472+
473+
// We're now connected to the server, so lets change server socket
474+
reverseProxy.on('data', listeners._r_data = function(data) {
475+
// Pass data to client
476+
if (socket.writable) {
477+
try {
478+
socket.write(data);
479+
}
480+
catch (e) {
481+
socket.end();
482+
reverseProxy.end();
483+
}
484+
}
485+
});
486+
487+
socket.on('data', listeners._data = function(data) {
488+
// Pass data from client to server
489+
try {
490+
reverseProxy.write(data);
491+
}
492+
catch (e) {
493+
reverseProxy.end();
494+
socket.end();
495+
}
496+
});
497+
498+
// Detach event listeners from reverseProxy
499+
function detach() {
500+
reverseProxy.removeListener('close', listeners._r_close);
501+
reverseProxy.removeListener('data', listeners._r_data);
502+
socket.removeListener('data', listeners._data);
503+
socket.removeListener('close', listeners._close);
504+
}
505+
506+
// Hook disconnections
507+
reverseProxy.on('end', listeners._r_close = function() {
508+
socket.end();
509+
detach();
510+
});
511+
512+
socket.on('end', listeners._close = function() {
513+
reverseProxy.end();
514+
detach();
515+
});
516+
};
480517

481518
// Client socket
482519
_socket(socket);
483-
484-
// If host is undefined
485-
// Get it from headers
486-
if (!host) {
487-
host = headers.Host;
488-
}
489520

490521
// Remote host address
491-
var remote_host = server + (port - 80 === 0 ? '' : ':' + port);
522+
var remoteHost = host + (port - 80 === 0 ? '' : ':' + port),
523+
agent = _getAgent(host, port);
492524

493525
// Change headers
494-
headers.Host = remote_host;
495-
headers.Origin = 'http://' + remote_host;
496-
497-
// Open request
498-
var p = manager.getPool(port, server);
499-
500-
p.getClient(function(client) {
501-
// Based on 'pool/main.js'
502-
var request = client.request('GET', req.url, headers);
503-
504-
var errorListener = function (error) {
505-
client.removeListener('error', errorListener);
506-
507-
// Remove the client from the pool's available clients since it has errored
508-
p.clients.splice(p.clients.indexOf(client), 1);
509-
socket.end();
510-
}
511-
512-
// Not disconnect on update
513-
client.on('upgrade', function(request, remote_socket, head) {
514-
// Prepare socket
515-
_socket(remote_socket, true);
526+
req.headers.host = remoteHost;
527+
req.headers.origin = 'http://' + host;
528+
529+
var opts = {
530+
host: host,
531+
port: port,
532+
agent: agent,
533+
method: 'GET',
534+
path: req.url,
535+
headers: req.headers
536+
}
516537

517-
// Emit event
518-
onUpgrade(remote_socket);
519-
});
538+
// Make the outgoing WebSocket request
539+
var request = http.request(opts, function () { });
540+
541+
// Not disconnect on update
542+
agent.on('upgrade', function(request, remoteSocket, head) {
543+
// Prepare socket
544+
_socket(remoteSocket, true);
520545

521-
client.on('error', errorListener);
522-
request.on('response', function (response) {
523-
response.on('end', function () {
524-
client.removeListener('error', errorListener);
525-
client.busy = false;
526-
p.onFree(client);
527-
})
528-
})
529-
client.busy = true;
530-
531-
var handshake;
546+
// Emit event
547+
onUpgrade(remoteSocket);
548+
});
549+
550+
var handshake;
551+
if (typeof request.socket !== 'undefined') {
532552
request.socket.on('data', handshake = function(data) {
533553
// Handshaking
534554

@@ -547,8 +567,8 @@ HttpProxy.prototype.proxyWebSocketRequest = function (port, server, host, data)
547567
data = data.slice(Buffer.byteLength(sdata), data.length);
548568

549569
// Replace host and origin
550-
sdata = sdata.replace(remote_host, host)
551-
.replace(remote_host, host);
570+
sdata = sdata.replace(remoteHost, host)
571+
.replace(remoteHost, host);
552572

553573
try {
554574
// Write printable
@@ -570,65 +590,19 @@ HttpProxy.prototype.proxyWebSocketRequest = function (port, server, host, data)
570590
// Remove data listener now that the 'handshake' is complete
571591
request.socket.removeListener('data', handshake);
572592
});
593+
}
573594

574-
// Write upgrade-head
575-
try {
576-
request.write(head);
577-
}
578-
catch(e) {
579-
request.end();
580-
socket.end();
581-
}
582-
self.unwatch(socket);
583-
});
584-
585-
// Request
586-
587-
function onUpgrade(reverse_proxy) {
588-
var listeners = {};
589-
590-
// We're now connected to the server, so lets change server socket
591-
reverse_proxy.on('data', listeners._r_data = function(data) {
592-
// Pass data to client
593-
if (socket.writable) {
594-
try {
595-
socket.write(data);
596-
}
597-
catch (e) {
598-
socket.end();
599-
reverse_proxy.end();
600-
}
601-
}
602-
});
603-
604-
socket.on('data', listeners._data = function(data) {
605-
// Pass data from client to server
606-
try {
607-
reverse_proxy.write(data);
608-
}
609-
catch (e) {
610-
reverse_proxy.end();
611-
socket.end();
612-
}
613-
});
614-
615-
// Detach event listeners from reverse_proxy
616-
function detach() {
617-
reverse_proxy.removeListener('close', listeners._r_close);
618-
reverse_proxy.removeListener('data', listeners._r_data);
619-
socket.removeListener('data', listeners._data);
620-
socket.removeListener('close', listeners._close);
621-
}
622-
623-
// Hook disconnections
624-
reverse_proxy.on('end', listeners._r_close = function() {
625-
socket.end();
626-
detach();
627-
});
628-
629-
socket.on('end', listeners._close = function() {
630-
reverse_proxy.end();
631-
detach();
632-
});
633-
};
595+
// Write upgrade-head
596+
try {
597+
request.write(head);
598+
}
599+
catch (ex) {
600+
request.end();
601+
socket.end();
602+
}
603+
604+
// If we have been passed buffered data, resume it.
605+
if (buffer && !errState) {
606+
buffer.resume();
607+
}
634608
};

0 commit comments

Comments
 (0)