Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
node-http-proxy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
node-http-proxy
Commits
973f19fd
Commit
973f19fd
authored
Mar 09, 2011
by
indexzero
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[doc] Added more documentation
parent
d8c54063
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
126 additions
and
64 deletions
+126
-64
demo.js
demo.js
+0
-1
lib/node-http-proxy.js
lib/node-http-proxy.js
+123
-59
lib/proxy-table.js
lib/proxy-table.js
+3
-4
No files found.
demo.js
View file @
973f19fd
...
@@ -39,7 +39,6 @@ var welcome = '\
...
@@ -39,7 +39,6 @@ var welcome = '\
# # # # # # # # #### # # #
\n
'
;
# # # # # # # # #### # # #
\n
'
;
util
.
puts
(
welcome
.
rainbow
.
bold
);
util
.
puts
(
welcome
.
rainbow
.
bold
);
//
//
// Basic Http Proxy Server
// Basic Http Proxy Server
//
//
...
...
lib/node-http-proxy.js
View file @
973f19fd
...
@@ -32,7 +32,13 @@ var util = require('util'),
...
@@ -32,7 +32,13 @@ var util = require('util'),
ProxyTable
=
require
(
'
./proxy-table
'
).
ProxyTable
,
ProxyTable
=
require
(
'
./proxy-table
'
).
ProxyTable
,
maxSockets
=
100
;
maxSockets
=
100
;
//
// ### function _getAgent (host, port)
// #### @host {string} Host of the agent to get
// #### @port {number} Port of the agent to get
// Retreives an agent from the `http` module
// and sets the `maxSockets` property appropriately.
//
function
_getAgent
(
host
,
port
)
{
function
_getAgent
(
host
,
port
)
{
//
//
// TODO (indexzero): Make this configurable for http / https
// TODO (indexzero): Make this configurable for http / https
...
@@ -42,17 +48,33 @@ function _getAgent (host, port) {
...
@@ -42,17 +48,33 @@ function _getAgent (host, port) {
return
agent
;
return
agent
;
}
}
//
// ### function getMaxSockets ()
// Returns the maximum number of sockets
// allowed on __every__ outgoing request
// made by __all__ instances of `HttpProxy`
//
exports
.
getMaxSockets
=
function
()
{
exports
.
getMaxSockets
=
function
()
{
return
maxSockets
;
return
maxSockets
;
};
};
//
// ### function setMaxSockets ()
// Sets the maximum number of sockets
// allowed on __every__ outgoing request
// made by __all__ instances of `HttpProxy`
//
exports
.
setMaxSockets
=
function
(
value
)
{
exports
.
setMaxSockets
=
function
(
value
)
{
maxSockets
=
value
;
maxSockets
=
value
;
};
};
//
// ### function createServer ([port, host, options], handler)
//
//
exports
.
createServer
=
function
()
{
exports
.
createServer
=
function
()
{
var
args
,
callback
,
port
,
host
,
forward
,
var
args
,
callback
,
port
,
host
,
forward
,
silent
,
proxyTable
,
options
=
{}
;
silent
,
options
,
proxy
,
server
;
args
=
Array
.
prototype
.
slice
.
call
(
arguments
);
args
=
Array
.
prototype
.
slice
.
call
(
arguments
);
callback
=
typeof
args
[
args
.
length
-
1
]
===
'
function
'
&&
args
.
pop
();
callback
=
typeof
args
[
args
.
length
-
1
]
===
'
function
'
&&
args
.
pop
();
...
@@ -69,9 +91,8 @@ exports.createServer = function () {
...
@@ -69,9 +91,8 @@ exports.createServer = function () {
}
}
}
}
var
proxy
=
new
HttpProxy
(
options
);
proxy
=
new
HttpProxy
(
options
);
server
=
http
.
createServer
(
function
(
req
,
res
)
{
var
server
=
http
.
createServer
(
function
(
req
,
res
)
{
winston
.
verbose
(
'
Incoming HTTP request to:
'
+
req
.
headers
.
host
+
req
.
url
);
winston
.
verbose
(
'
Incoming HTTP request to:
'
+
req
.
headers
.
host
+
req
.
url
);
// If we were passed a callback to process the request
// If we were passed a callback to process the request
...
@@ -98,13 +119,14 @@ exports.createServer = function () {
...
@@ -98,13 +119,14 @@ exports.createServer = function () {
proxy
.
on
(
'
routes
'
,
function
(
routes
)
{
proxy
.
on
(
'
routes
'
,
function
(
routes
)
{
server
.
emit
(
'
routes
'
,
routes
);
server
.
emit
(
'
routes
'
,
routes
);
})
})
;
if
(
!
callback
)
{
if
(
!
callback
)
{
// WebSocket support: if callback is empty tunnel
// WebSocket support: if callback is empty tunnel
// websocket request automatically
// websocket request automatically
server
.
on
(
'
upgrade
'
,
function
(
req
,
socket
,
head
)
{
server
.
on
(
'
upgrade
'
,
function
(
req
,
socket
,
head
)
{
// Tunnel websocket requests too
// Tunnel websocket requests too
proxy
.
proxyWebSocketRequest
(
port
,
host
);
proxy
.
proxyWebSocketRequest
(
port
,
host
);
});
});
}
}
...
@@ -112,6 +134,25 @@ exports.createServer = function () {
...
@@ -112,6 +134,25 @@ exports.createServer = function () {
return
server
;
return
server
;
};
};
//
// ### function HttpProxy (options)
// #### @options {Object} Options for this instance.
// Constructor function for new instances of HttpProxy responsible
// for managing the life-cycle of streaming reverse proxyied HTTP requests.
//
// Example options:
//
// {
// router: {
// 'foo.com': 'localhost:8080',
// 'bar.com': 'localhost:8081'
// },
// forward: {
// host: 'localhost',
// port: 9001
// }
// }
//
var
HttpProxy
=
exports
.
HttpProxy
=
function
(
options
)
{
var
HttpProxy
=
exports
.
HttpProxy
=
function
(
options
)
{
events
.
EventEmitter
.
call
(
this
);
events
.
EventEmitter
.
call
(
this
);
...
@@ -127,38 +168,36 @@ var HttpProxy = exports.HttpProxy = function (options) {
...
@@ -127,38 +168,36 @@ var HttpProxy = exports.HttpProxy = function (options) {
}
}
};
};
// Inherit from events.EventEmitter
util
.
inherits
(
HttpProxy
,
events
.
EventEmitter
);
util
.
inherits
(
HttpProxy
,
events
.
EventEmitter
);
HttpProxy
.
prototype
.
close
=
function
()
{
//
if
(
this
.
proxyTable
)
this
.
proxyTable
.
close
();
// ### function pause (obj)
};
// #### @obj {Object} Object to pause events from
// Pause `data` and `end` events on the given `obj`.
/**
// Consumers of HttpProxy performing async tasks
* Pause `data` and `end` events on the given `obj`.
// __must__ utilize this utility, to re-emit data once
* Middleware performing async tasks _should_ utilize
// the async operation has completed, otherwise these
* this utility (or similar), to re-emit data once
// __events will be lost.__
* the async operation has completed, otherwise these
//
* events may be lost.
// var pause = httpProxy.pause(req);
*
// fs.readFile(path, function(){
* var pause = utils.pause(req);
// httpProxy.proxyRequest(req, res, host, port, paused);
* fs.readFile(path, function(){
// });
* next();
//
* pause.resume();
// __Attribution:__ This approach is based heavily on
* });
// [Connect](https://github.com/senchalabs/connect/blob/master/lib/utils.js#L157).
*
// However, this is not a big leap from the implementation in node-http-proxy < 0.4.0.
* @param {Object} obj
// This simply chooses to manage the scope of the events on a new Object literal as opposed to
* @return {Object}
// [on the HttpProxy instance](https://github.com/nodejitsu/node-http-proxy/blob/v0.3.1/lib/node-http-proxy.js#L154).
* @api public
//
*/
HttpProxy
.
prototype
.
pause
=
function
(
obj
)
{
HttpProxy
.
prototype
.
pause
=
function
(
obj
)
{
var
onData
,
onEnd
,
events
=
[];
var
onData
,
onEnd
,
events
=
[];
// buffer data
obj
.
on
(
'
data
'
,
onData
=
function
(
data
,
encoding
)
{
obj
.
on
(
'
data
'
,
onData
=
function
(
data
,
encoding
)
{
events
.
push
([
'
data
'
,
data
,
encoding
]);
events
.
push
([
'
data
'
,
data
,
encoding
]);
});
});
// buffer end
obj
.
on
(
'
end
'
,
onEnd
=
function
(
data
,
encoding
)
{
obj
.
on
(
'
end
'
,
onEnd
=
function
(
data
,
encoding
)
{
events
.
push
([
'
end
'
,
data
,
encoding
]);
events
.
push
([
'
end
'
,
data
,
encoding
]);
});
});
...
@@ -177,8 +216,25 @@ HttpProxy.prototype.pause = function (obj) {
...
@@ -177,8 +216,25 @@ HttpProxy.prototype.pause = function (obj) {
};
};
};
};
//
// ### function close ()
// Frees the resources associated with this instance,
// if they exist.
//
HttpProxy
.
prototype
.
close
=
function
()
{
if
(
this
.
proxyTable
)
this
.
proxyTable
.
close
();
};
//
// ### function proxyRequest (req, res, [port, host, paused])
// #### @req {ServerRequest} Incoming HTTP Request to proxy.
// #### @res {ServerResponse} Outgoing HTTP Request to write proxied data to.
// #### @port {number} **Optional** Port to use on the proxy target host.
// #### @host {string} **Optional** Host of the proxy target.
// #### @paused {Object} **Optional** Result from `httpProxy.pause(req)`
//
HttpProxy
.
prototype
.
proxyRequest
=
function
(
req
,
res
,
port
,
host
,
paused
)
{
HttpProxy
.
prototype
.
proxyRequest
=
function
(
req
,
res
,
port
,
host
,
paused
)
{
var
self
=
this
,
reverseProxy
,
location
;
var
self
=
this
,
reverseProxy
,
location
,
errState
=
false
;
//
//
// Check the proxy table for this instance to see if we need
// Check the proxy table for this instance to see if we need
...
@@ -189,6 +245,10 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
...
@@ -189,6 +245,10 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
if
(
this
.
proxyTable
&&
!
host
)
{
if
(
this
.
proxyTable
&&
!
host
)
{
location
=
this
.
proxyTable
.
getProxyLocation
(
req
);
location
=
this
.
proxyTable
.
getProxyLocation
(
req
);
//
// If no location is returned from the ProxyTable instance
// then respond with `404` since we do not have a valid proxy target.
//
if
(
!
location
)
{
if
(
!
location
)
{
res
.
writeHead
(
404
);
res
.
writeHead
(
404
);
return
res
.
end
();
return
res
.
end
();
...
@@ -198,36 +258,34 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
...
@@ -198,36 +258,34 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
// 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:
// only the following arguments are valid:
//
//
// *
proxy.proxyRequest(req, res, port, host, paused)
: This will be skipped
// *
`proxy.proxyRequest(req, res, port, host, paused)`
: This will be skipped
// *
proxy.proxyRequest(req, res, paused)
: Paused will get updated appropriately
// *
`proxy.proxyRequest(req, res, paused)`
: Paused will get updated appropriately
// *
proxy.proxyRequest(req, res)
: No effect `undefined = undefined`
// *
`proxy.proxyRequest(req, res)`
: No effect `undefined = undefined`
//
//
paused
=
port
;
paused
=
port
;
port
=
location
.
port
;
port
=
location
.
port
;
host
=
location
.
host
;
host
=
location
.
host
;
}
}
//
// If forwarding is enabled for this instance, foward proxy the
// specified request to the address provided in `this.options.forward`
//
if
(
this
.
options
.
forward
)
{
if
(
this
.
options
.
forward
)
{
winston
.
verbose
(
'
Forwarding HTTP request to:
'
+
this
.
options
.
forward
.
host
+
'
:
'
+
this
.
options
.
forward
.
port
);
winston
.
verbose
(
'
Forwarding HTTP request to:
'
+
this
.
options
.
forward
.
host
+
'
:
'
+
this
.
options
.
forward
.
port
);
this
.
_forwardRequest
(
req
);
this
.
_forwardRequest
(
req
);
}
}
// Create an error handler so we can use it temporarily
function
proxyError
(
err
)
{
function
error
(
obj
)
{
errState
=
true
;
var
fn
=
function
(
err
)
{
res
.
writeHead
(
500
,
{
'
Content-Type
'
:
'
text/plain
'
});
res
.
writeHead
(
500
,
{
'
Content-Type
'
:
'
text/plain
'
});
if
(
req
.
method
!==
'
HEAD
'
)
{
if
(
req
.
method
!==
'
HEAD
'
)
{
res
.
write
(
'
An error has occurred:
'
+
JSON
.
stringify
(
err
));
res
.
write
(
'
An error has occurred:
'
+
JSON
.
stringify
(
err
));
}
}
// Response end may never come so removeListener here
obj
.
removeListener
(
'
error
'
,
fn
);
res
.
end
();
res
.
end
();
};
}
return
fn
;
};
// Open new HTTP request to internal resource with will act as a reverse proxy pass
// Open new HTTP request to internal resource with will act as a reverse proxy pass
reverseProxy
=
http
.
request
({
reverseProxy
=
http
.
request
({
...
@@ -263,26 +321,31 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
...
@@ -263,26 +321,31 @@ HttpProxy.prototype.proxyRequest = function (req, res, port, host, paused) {
// Add event listener for end of proxied response
// Add event listener for end of proxied response
response
.
on
(
'
end
'
,
function
()
{
response
.
on
(
'
end
'
,
function
()
{
reverseProxy
.
removeListener
(
'
error
'
,
reverseProxyError
);
if
(
!
errState
)
{
reverseProxy
.
removeListener
(
'
error
'
,
proxyError
);
res
.
end
();
res
.
end
();
}
});
});
});
});
// Add a listener for the connection timeout event
// Add a listener for the connection timeout event
var
reverseProxyError
=
error
(
reverseProxy
);
reverseProxy
.
once
(
'
error
'
,
proxyError
);
reverseProxy
.
on
(
'
error
'
,
reverseProxyError
);
// Chunk the client request body as chunks from the proxied request come in
// Chunk the client request body as chunks from the proxied request come in
req
.
on
(
'
data
'
,
function
(
chunk
)
{
req
.
on
(
'
data
'
,
function
(
chunk
)
{
if
(
!
errState
)
{
reverseProxy
.
write
(
chunk
);
reverseProxy
.
write
(
chunk
);
}
});
});
// At the end of the client request, we are going to stop the proxied request
// At the end of the client request, we are going to stop the proxied request
req
.
on
(
'
end
'
,
function
()
{
req
.
on
(
'
end
'
,
function
()
{
if
(
!
errState
)
{
reverseProxy
.
end
();
reverseProxy
.
end
();
}
});
});
if
(
paused
)
{
if
(
paused
&&
!
errState
)
{
paused
.
resume
();
paused
.
resume
();
}
}
};
};
...
@@ -308,11 +371,12 @@ HttpProxy.prototype._forwardRequest = function (req) {
...
@@ -308,11 +371,12 @@ HttpProxy.prototype._forwardRequest = function (req) {
//
//
});
});
// Add a listener for the connection timeout event
// Add a listener for the connection timeout event
.
forwardProxy
.
on
(
'
error
'
,
function
(
err
)
{
//
// Remark: Ignoring this error in the event
// Remark: Ignoring this error in the event
// forward target doesn't exist.
// forward target doesn't exist.
});
//
forwardProxy
.
on
(
'
error
'
,
function
(
err
)
{
});
// Chunk the client request body as chunks from the proxied request come in
// Chunk the client request body as chunks from the proxied request come in
req
.
on
(
'
data
'
,
function
(
chunk
)
{
req
.
on
(
'
data
'
,
function
(
chunk
)
{
...
...
lib/proxy-table.js
View file @
973f19fd
...
@@ -26,7 +26,8 @@
...
@@ -26,7 +26,8 @@
var
util
=
require
(
'
util
'
),
var
util
=
require
(
'
util
'
),
events
=
require
(
'
events
'
),
events
=
require
(
'
events
'
),
fs
=
require
(
'
fs
'
);
fs
=
require
(
'
fs
'
),
winston
=
require
(
'
winston
'
);
//
//
// ### function ProxyTable (router, silent)
// ### function ProxyTable (router, silent)
...
@@ -109,9 +110,7 @@ ProxyTable.prototype.getProxyLocation = function (req) {
...
@@ -109,9 +110,7 @@ ProxyTable.prototype.getProxyLocation = function (req) {
host
=
location
[
0
],
host
=
location
[
0
],
port
=
location
.
length
===
1
?
80
:
location
[
1
];
port
=
location
.
length
===
1
?
80
:
location
[
1
];
if
(
!
this
.
silent
)
{
winston
.
verbose
(
'
Proxy Table proxying request to:
'
+
host
+
'
:
'
+
port
);
util
.
log
(
'
Proxy Table proxying request to:
'
+
host
+
'
:
'
+
port
);
}
return
{
return
{
port
:
port
,
port
:
port
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment