diff --git a/docs/node-http-proxy.html b/docs/node-http-proxy.html index bd2fb82..fbcc8b1 100644 --- a/docs/node-http-proxy.html +++ b/docs/node-http-proxy.html @@ -30,29 +30,29 @@ events = require('events'), winston = require('winston'), ProxyTable = require('./proxy-table').ProxyTable, - maxSockets = 100;
exports.version = [0, 4, 0];Retreives an agent from the http module
-and sets the maxSockets property appropriately.
function _getAgent (host, port) {TODO (indexzero): Make this configurable for http / https
var agent = http.getAgent(host, port);
+and sets the maxSockets property appropriately. function _getAgent (host, port) {TODO (indexzero): Make this configurable for http / https
var agent = http.getAgent(host, port);
agent.maxSockets = maxSockets;
return agent;
-}Returns the maximum number of sockets
allowed on every outgoing request
made by all instances of HttpProxy
exports.getMaxSockets = function () {
return maxSockets;
-};Sets the maximum number of sockets
allowed on every outgoing request
made by all instances of HttpProxy
exports.setMaxSockets = function (value) {
maxSockets = value;
-};HttpProxy
proxy = new HttpProxy(options);
server = http.createServer(function (req, res) {
- winston.verbose('Incoming HTTP request to: ' + req.headers.host + req.url); If we were passed a callback to process the request + winston.verbose('Incoming HTTP request to: ' + req.headers.host + req.url);
If we were passed a callback to process the request or response in some way, then call it.
if (callback) {
callback(req, res, proxy);
}
@@ -114,14 +114,14 @@ or response in some way, then call it. WebSocket support: if callback is empty tunnel -websocket request automatically
server.on('upgrade', function(req, socket, head) {Tunnel websocket requests too
+ if (!callback) {WebSocket support: if callback is empty tunnel +websocket request automatically
server.on('upgrade', function(req, socket, head) {Tunnel websocket requests too
proxy.proxyWebSocketRequest(port, host);
});
}
return server;
-};Inherit from events.EventEmitter
util.inherits(HttpProxy, events.EventEmitter);Inherit from events.EventEmitter
util.inherits(HttpProxy, events.EventEmitter);Frees the resources associated with this instance, if they exist.
HttpProxy.prototype.close = function () {
if (this.proxyTable) this.proxyTable.close();
-};httpProxy.buffer(req)HttpProxy.prototype.proxyRequest = function (req, res, port, host, buffer) {
- var self = this, reverseProxy, location, errState = false;
- Check the proxy table for this instance to see if we need + var self = this, reverseProxy, location, errState = false, opts; +
Check the proxy table for this instance to see if we need
to get the proxy location for the request supplied. We will
always ignore the proxyTable if an explicit port and host
arguments are supplied to proxyRequest.
if (this.proxyTable && !host) {
location = this.proxyTable.getProxyLocation(req);
- If no location is returned from the ProxyTable instance +
If no location is returned from the ProxyTable instance
then respond with 404 since we do not have a valid proxy target.
if (!location) {
res.writeHead(404);
return res.end();
}
- When using the ProxyTable in conjunction with an HttpProxy instance +
When using the ProxyTable in conjunction with an HttpProxy instance only the following arguments are valid:
If forwarding is enabled for this instance, foward proxy the +
If forwarding is enabled for this instance, foward proxy the
specified request to the address provided in this.options.forward
if (this.options.forward) {
winston.verbose('Forwarding HTTP request to: ' + this.options.forward.host + ':' + this.options.forward.port);
this._forwardRequest(req);
}
- host / port.
res.end();
}
- Open new HTTP request to internal resource with will act as a reverse proxy pass
reverseProxy = http.request({
+
+ var opts = {
host: host,
port: port,
agent: _getAgent(host, port),
method: req.method,
path: req.url,
headers: req.headers
- }, function (response) {
- Process the reverseProxy response when it's received.
if (response.headers.connection) {
+ };
+ Force the connection header to be 'close' until
+node.js core re-implements 'keep-alive'.
opts.headers['connection'] = 'close';
+ Open new HTTP request to internal resource with will act as a reverse proxy pass
reverseProxy = http.request(opts, function (response) {
+ Process the reverseProxy response when it's received.
if (response.headers.connection) {
if (req.headers.connection) response.headers.connection = req.headers.connection;
else response.headers.connection = 'close';
- }Set the headers of the client response
res.writeHead(response.statusCode, response.headers);response.statusCode === 304: No 'data' event and no 'end'
if (response.statusCode === 304) {
+ }Set the headers of the client response
res.writeHead(response.statusCode, response.headers);response.statusCode === 304: No 'data' event and no 'end'
if (response.statusCode === 304) {
return res.end();
- }For each data chunk received from the reverseProxy
+ }
For each data chunk received from the reverseProxy
response write it to the outgoing res.
response.on('data', function (chunk) {
if (req.method !== 'HEAD') {
res.write(chunk);
}
- });When the reverseProxy response ends, end the
+ });
When the reverseProxy response ends, end the
corresponding outgoing res unless we have entered
an error state. In which case, assume res.end() has
already been called and the 'error' event listener
@@ -283,68 +287,65 @@ removed.
Handle 'error' events from the reverseProxy.
reverseProxy.once('error', proxyError);
- For each data chunk received from the incoming
+
Handle 'error' events from the reverseProxy.
reverseProxy.once('error', proxyError);
+ For each data chunk received from the incoming
req write it to the reverseProxy request.
req.on('data', function (chunk) {
if (!errState) {
reverseProxy.write(chunk);
}
- });When the incoming req ends, end the corresponding reverseProxy
-request unless we have entered an error state.
req.on('end', function () {Remark (indexzero | 3/10/2011): This is a short-term workaround for a suspect error from net.js when
-http.ClientRequest.end() is called in reproducable, but uninvestigated scenarios
net.js:313
- throw new Error('Socket.end() called already; cannot write.');
- ^
-Error: Socket.end() called already; cannot write.
- at Socket.write (net.js:313:13)
- if (!errState /*&& (!reverseProxy.socket || reverseProxy.socket._writeQueueLast() !== 42)*/) {
+ });When the incoming req ends, end the corresponding reverseProxy
+request unless we have entered an error state.
req.on('end', function () {
+ if (!errState) {
reverseProxy.end();
}
- });If we have been passed buffered data, resume it.
if (buffer && !errState) {
+ });If we have been passed buffered data, resume it.
if (buffer && !errState) {
buffer.resume();
}
};
- Forwards the specified req to the location specified
by this.options.forward ignoring errors and the subsequent response.
HttpProxy.prototype._forwardRequest = function (req) {
- var self = this, port, host, forwardProxy;
+ var self = this, port, host, forwardProxy, opts;
port = this.options.forward.port;
host = this.options.forward.host;
- Open new HTTP request to internal resource with will act as a reverse proxy pass
forwardProxy = http.request({
+
+ opts = {
host: host,
port: port,
agent: _getAgent(host, port),
method: req.method,
path: req.url,
headers: req.headers
- }, function (response) {Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy. + }; +
Force the connection header to be 'close' until
+node.js core re-implements 'keep-alive'.
opts.headers['connection'] = 'close';
+ Open new HTTP request to internal resource with will act as a reverse proxy pass
forwardProxy = http.request(opts, function (response) {Ignore the response from the forward proxy since this is a 'fire-and-forget' proxy. Remark (indexzero): We will eventually emit a 'forward' event here for performance tuning.
});
- Add a listener for the connection timeout event.
+Add a listener for the connection timeout event.
Remark: Ignoring this error in the event - forward target doesn't exist.
forwardProxy.on('error', function (err) { });Chunk the client request body as chunks from the proxied request come in
req.on('data', function (chunk) {
+ forward target doesn't exist. forwardProxy.once('error', function (err) { });Chunk the client request body as chunks from the proxied request come in
req.on('data', function (chunk) {
forwardProxy.write(chunk);
- })At the end of the client request, we are going to stop the proxied request
req.on('end', function () {
+ })At the end of the client request, we are going to stop the proxied request
req.on('end', function () {
forwardProxy.end();
});
};
HttpProxy.prototype.proxyWebSocketRequest = function (port, server, host, data) {
var self = this, req = self.req, socket = self.sock, head = self.head,
- headers = new _headers(req.headers), CRLF = '\r\n';Will generate clone of headers + headers = new _headers(req.headers), CRLF = '\r\n';
Will generate clone of headers To not change original
function _headers(headers) {
var h = {};
for (var i in headers) {
h[i] = headers[i];
}
return h;
- }WebSocket requests has method = GET
if (req.method !== 'GET' || headers.upgrade.toLowerCase() !== 'websocket') {This request is not WebSocket request
return;
- }Turn of all bufferings + }
WebSocket requests has method = GET
if (req.method !== 'GET' || headers.upgrade.toLowerCase() !== 'websocket') {This request is not WebSocket request
return;
+ }Turn of all bufferings For server set KeepAlive For client set encoding
function _socket(socket, server) {
socket.setTimeout(0);
@@ -355,20 +356,20 @@ For client set encoding Client socket
_socket(socket);If host is undefined + }
Client socket
_socket(socket);If host is undefined Get it from headers
if (!host) {
host = headers.Host;
}
- Remote host address
var remote_host = server + (port - 80 === 0 ? '' : ':' + port);Change headers
headers.Host = remote_host;
- headers.Origin = 'http://' + remote_host;Open request
var p = manager.getPool(port, server);
+ Remote host address
var remote_host = server + (port - 80 === 0 ? '' : ':' + port);Change headers
headers.Host = remote_host;
+ headers.Origin = 'http://' + remote_host;Open request
var p = manager.getPool(port, server);
- p.getClient(function(client) {Based on 'pool/main.js'
var request = client.request('GET', req.url, headers);
+ p.getClient(function(client) {Based on 'pool/main.js'
var request = client.request('GET', req.url, headers);
var errorListener = function (error) {
client.removeListener('error', errorListener);
- Remove the client from the pool's available clients since it has errored
p.clients.splice(p.clients.indexOf(client), 1);
+ Remove the client from the pool's available clients since it has errored
p.clients.splice(p.clients.indexOf(client), 1);
socket.end();
- }Not disconnect on update
client.on('upgrade', function(request, remote_socket, head) {Prepare socket
_socket(remote_socket, true);Emit event
onUpgrade(remote_socket);
+ }Not disconnect on update
client.on('upgrade', function(request, remote_socket, head) {Prepare socket
_socket(remote_socket, true);Emit event
onUpgrade(remote_socket);
});
client.on('error', errorListener);
@@ -382,23 +383,23 @@ Get it from headers Handshaking
Ok, kind of harmfull part of code + request.socket.on('data', handshake = function(data) {
Handshaking
Ok, kind of harmfull part of code Socket.IO is sending hash at the end of handshake If protocol = 76 But we need to replace 'host' and 'origin' in response So we split data to printable data and to non-printable -(Non-printable will come after double-CRLF)
var sdata = data.toString();Get Printable
sdata = sdata.substr(0, sdata.search(CRLF + CRLF));Get Non-Printable
data = data.slice(Buffer.byteLength(sdata), data.length);Replace host and origin
sdata = sdata.replace(remote_host, host)
+(Non-printable will come after double-CRLF) var sdata = data.toString();Get Printable
sdata = sdata.substr(0, sdata.search(CRLF + CRLF));Get Non-Printable
data = data.slice(Buffer.byteLength(sdata), data.length);Replace host and origin
sdata = sdata.replace(remote_host, host)
.replace(remote_host, host);
- try {Write printable
socket.write(sdata);Write non-printable
socket.write(data);
+ try {Write printable
socket.write(sdata);Write non-printable
socket.write(data);
}
catch (e) {
request.end();
socket.end();
- }Catch socket errors
socket.on('error', function() {
+ }Catch socket errors
socket.on('error', function() {
request.end();
- });Remove data listener now that the 'handshake' is complete
request.socket.removeListener('data', handshake);
- });Write upgrade-head
try {
+ });Remove data listener now that the 'handshake' is complete
request.socket.removeListener('data', handshake);
+ });Write upgrade-head
try {
request.write(head);
}
catch(e) {
@@ -406,9 +407,9 @@ So we split data to printable data and to non-printable
socket.end();
}
self.unwatch(socket);
- });Request
function onUpgrade(reverse_proxy) {
+ });Request
function onUpgrade(reverse_proxy) {
var listeners = {};
- We're now connected to the server, so lets change server socket
reverse_proxy.on('data', listeners._r_data = function(data) {Pass data to client
if (socket.writable) {
+ We're now connected to the server, so lets change server socket
reverse_proxy.on('data', listeners._r_data = function(data) {Pass data to client
if (socket.writable) {
try {
socket.write(data);
}
@@ -419,19 +420,19 @@ So we split data to printable data and to non-printable
}
});
- socket.on('data', listeners._data = function(data) {Pass data from client to server
try {
+ socket.on('data', listeners._data = function(data) {Pass data from client to server
try {
reverse_proxy.write(data);
}
catch (e) {
reverse_proxy.end();
socket.end();
}
- });Detach event listeners from reverse_proxy
function detach() {
+ });Detach event listeners from reverse_proxy
function detach() {
reverse_proxy.removeListener('close', listeners._r_close);
reverse_proxy.removeListener('data', listeners._r_data);
socket.removeListener('data', listeners._data);
socket.removeListener('close', listeners._close);
- }Hook disconnections
reverse_proxy.on('end', listeners._r_close = function() {
+ }Hook disconnections
reverse_proxy.on('end', listeners._r_close = function() {
socket.end();
detach();
});