Skip to content
This repository
Browse code

[api] First commit of http-proxy

  • Loading branch information...
commit 30b68c153270619119ec36615bb54ee7a2816ecc 0 parents
Charlie Robbins authored July 24, 2010
0  README.md
Source Rendered
No changes.
120  lib/node-proxy.js
... ...
@@ -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
+};
75  test/node-proxy-test.js
... ...
@@ -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 notes on commit 30b68c1

Please sign in to comment.
Something went wrong with that request. Please try again.