Skip to content

Commit 30b68c1

Browse files
committed
[api] First commit of http-proxy
0 parents  commit 30b68c1

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

README.md

Whitespace-only changes.

lib/node-proxy.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* node-proxy.js: Reverse proxy for node.js
3+
*
4+
* (C) 2010 Charlie Robbins
5+
* MIT LICENSE
6+
*
7+
*/
8+
9+
var sys = require('sys'),
10+
http = require('http'),
11+
events = require('events');
12+
13+
//
14+
// Creates a new instance of NodeProxy
15+
//
16+
//exports.create = function (req, res) {
17+
// return new exports.nodeProxy(req, res);
18+
//};
19+
20+
//
21+
// The NodeProxy factory
22+
//
23+
exports.NodeProxy = function () {
24+
var self = this;
25+
this.emitter = new(events.EventEmitter);
26+
27+
// If we were passed more than two arguments,
28+
// assume they are request and response.
29+
if(arguments.length >= 2) {
30+
this.init(arguments[0], arguments[1]);
31+
}
32+
};
33+
34+
exports.NodeProxy.prototype = {
35+
toArray: function (obj){
36+
var len = obj.length,
37+
arr = new Array(len);
38+
for (var i = 0; i < len; ++i) {
39+
arr[i] = obj[i];
40+
}
41+
return arr;
42+
},
43+
44+
init: function (req, res) {
45+
this.events = [];
46+
47+
this.onData = function () {
48+
self.events.push(["data"].concat(self.toArray(arguments)));
49+
};
50+
this.onEnd = function () {
51+
self.events.push(["end"].concat(self.toArray(arguments)));
52+
};
53+
54+
req.addListener("data", this.onData);
55+
req.addListener("end", this.onEnd);
56+
},
57+
58+
proxyRequest: function (server, port, req, res) {
59+
// Remark: nodeProxy.body exists solely for testability
60+
this.body = '';
61+
var self = this;
62+
63+
// Open new HTTP request to internal resource with will act as a reverse proxy pass
64+
var c = http.createClient(port, server);
65+
66+
// Make request to internal server, passing along the method and headers
67+
var reverse_proxy = c.request(req.method, req.url, req.headers);
68+
69+
// Add a listener for the connection timeout event
70+
reverse_proxy.connection.addListener('error', function(err) {
71+
res.writeHead(200, {'Content-Type': 'text/plain'});
72+
73+
if(req.method !== 'HEAD') {
74+
res.write('Not a HEAD request');
75+
}
76+
77+
res.end();
78+
});
79+
80+
// Add a listener for the reverse_proxy response event
81+
reverse_proxy.addListener("response", function (response) {
82+
// Set the response headers of the client response
83+
res.writeHead(response.statusCode, response.headers);
84+
85+
// Add event handler for the proxied response in chunks
86+
response.addListener("data", function (chunk) {
87+
if(req.method !== 'HEAD') {
88+
res.write(chunk, 'binary');
89+
this.body += chunk;
90+
}
91+
});
92+
93+
// Add event listener for end of proxied response
94+
response.addListener("end", function () {
95+
res.end();
96+
});
97+
});
98+
99+
// Chunk the client request body as chunks from the proxied request come in
100+
req.addListener("data", function (chunk) {
101+
reverse_proxy.write(chunk, 'binary');
102+
})
103+
104+
// At the end of the client request, we are going to stop the proxied request
105+
req.addListener("end", function () {
106+
// Remark: Emit the end event for testability
107+
self.emitter.emit('something', self.body);
108+
109+
reverse_proxy.end();
110+
});
111+
112+
req.removeListener('data', this.onData);
113+
req.removeListener('end', this.onEnd);
114+
115+
// Rebroadcast any events that have been buffered
116+
for (var i = 0, len = this.events.length; i < len; ++i) {
117+
req.emit.apply(req, this.events[i]);
118+
}
119+
}
120+
};

test/node-proxy-test.js

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* node-proxy-test.js: Tests for node-proxy. Reverse proxy for node.js
3+
*
4+
* (C) 2010 Charlie Robbins
5+
* MIT LICENSE
6+
*
7+
*/
8+
9+
var vows = require('vows'),
10+
sys = require('sys'),
11+
assert = require('assert'),
12+
http = require('http');
13+
14+
require.paths.unshift(require('path').join(__dirname, '../lib/'));
15+
16+
var NodeProxy = require('node-proxy').NodeProxy;
17+
18+
//
19+
// Simple 'hello world' response for test purposes
20+
//
21+
var helloWorld = function(req, res) {
22+
res.sendHeader(200, {'Content-Type': 'text/plain'});
23+
res.write('hello world')
24+
res.end();
25+
};
26+
27+
//
28+
// Creates the reverse proxy server
29+
//
30+
var startProxy = function (server, port, proxy) {
31+
http.createServer(function (req, res){
32+
// Initialize the nodeProxy and start proxying the request
33+
proxy.init(req, res);
34+
proxy.proxyRequest(server, port, req, res);
35+
}).listen(8080);
36+
};
37+
38+
//
39+
// Creates the 'hellonode' server
40+
//
41+
var startProxyTarget = function () {
42+
http.createServer(function (req, res) {
43+
helloWorld(req, res);
44+
}).listen(8081);
45+
};
46+
47+
//
48+
// The default test bootstrapper
49+
//
50+
var startProxyTest = function () {
51+
var proxy = new (NodeProxy);
52+
startProxy('127.0.0.1', 8081, proxy);
53+
startProxyTarget();
54+
return proxy;
55+
};
56+
57+
var proxy = startProxyTest();
58+
proxy.emitter.addListener('something', function (body) {
59+
sys.puts(body);
60+
})
61+
62+
/*vows.describe('node-proxy').addBatch({
63+
"When an incoming request is proxied to the helloNode server" : {
64+
topic: function () {
65+
var proxy = startProxyTest();
66+
proxy.emitter.addListener('end', this.callback);
67+
var client = http.createClient(8080, '127.0.0.1');
68+
client.request('GET', '/');
69+
},
70+
"it should received 'hello world'": function (num) {
71+
sys.puts('got callback');
72+
//assert.equal(body, 'hello world');
73+
}
74+
}
75+
}).export(module);*/

0 commit comments

Comments
 (0)