Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

17-line raw tcp server using through that passes the bounce test

  • Loading branch information...
commit cf6bdf5804b610312629ccb097ce4b179cdfadfd 1 parent 3d01108
@substack authored
Showing with 110 additions and 93 deletions.
  1. +13 −93 index.js
  2. +97 −0 index.js_
View
106 index.js
@@ -1,97 +1,17 @@
-var httpRaw = require('http-raw');
+var net = require('net');
+var through = require('through');
-var insertHeaders = require('./lib/insert_headers');
-var updatePath = require('./lib/update_path');
-var parseArgs = require('./lib/parse_args');
-
-var bouncy = module.exports = function (opts, cb) {
- if (typeof opts === 'function') {
- cb = opts;
- opts = {};
- }
-
- var createServer = opts && opts.key && opts.cert
- ? function (cb_) { return httpRaw.https(opts, cb_) }
- : httpRaw.http
- ;
-
- var server = createServer(function (req, res) {
- var bounce = makeBounce(req, res);
- if (cb.length === 3) {
- cb(req, res, bounce);
- }
- else cb(req, bounce);
- });
-
- server.on('upgrade', function (req, sock, buf) {
- if (req.headers.upgrade || req.method === 'CONNECT') {
- var bounce = makeBounce(req, sock);
- cb(req, bounce);
-
- sock.on('end', function () {
- req.destroy();
- });
- }
+module.exports = function (cb) {
+ var server = net.createServer(function (stream) {
+ var src = through();
+ src.pause();
+ stream.pipe(src);
+
+ var bounce = function (dst) {
+ src.pipe(dst).pipe(stream);
+ src.resume();
+ };
+ cb({}, bounce);
});
-
return server;
};
-
-
-function makeBounce (req, res) {
- var bounce = function (stream, opts) {
- var rs = req.createRawStream();
- var ws = res.createRawStream && res.createRawStream() || res;
-
- if (!stream || !stream.write) {
- opts = parseArgs(arguments);
- stream = opts.stream;
- }
- if (!opts) opts = {};
-
- if (!opts.headers) opts.headers = {};
- if (!('x-forwarded-for' in opts.headers)) {
- opts.headers['x-forwarded-for'] = req.connection.remoteAddress;
- }
- if (!('x-forwarded-port' in opts.headers)) {
- var m = (req.headers.host || '').match(/:(\d+)/);
- opts.headers['x-forwarded-port'] = m && m[1] || 80;
- }
- if (!('x-forwarded-proto' in opts.headers)) {
- opts.headers['x-forwarded-proto'] =
- req.connection.encrypted ? 'https' : 'http';
- }
-
- insertHeaders(rs.buffers, opts.headers);
- if (opts.path) updatePath(rs.buffers, opts.path);
-
- if (stream.writable) {
- rs.pipe(stream, { end : false });
- stream.pipe(ws);
- }
- else if (opts.emitter) {
- opts.emitter.emit('drop', ws);
- }
-
- stream.on('error', function (err) {
- if (stream.listeners('error').length === 1) {
- // destroy the request and stream if nobody is listening
- req.destroy();
- stream.destroy();
- }
- });
-
- stream.on('close', function () {
- _onclose.forEach(function (fn) { fn() });
- });
-
- return stream;
- };
-
- var _onclose = [];
- bounce._onclose = function (fn) {
- _onclose.push(fn);
- };
-
- return bounce;
-}
View
97 index.js_
@@ -0,0 +1,97 @@
+var httpRaw = require('http-raw');
+
+var insertHeaders = require('./lib/insert_headers');
+var updatePath = require('./lib/update_path');
+var parseArgs = require('./lib/parse_args');
+
+var bouncy = module.exports = function (opts, cb) {
+ if (typeof opts === 'function') {
+ cb = opts;
+ opts = {};
+ }
+
+ var createServer = opts && opts.key && opts.cert
+ ? function (cb_) { return httpRaw.https(opts, cb_) }
+ : httpRaw.http
+ ;
+
+ var server = createServer(function (req, res) {
+ var bounce = makeBounce(req, res);
+ if (cb.length === 3) {
+ cb(req, res, bounce);
+ }
+ else cb(req, bounce);
+ });
+
+ server.on('upgrade', function (req, sock, buf) {
+ if (req.headers.upgrade || req.method === 'CONNECT') {
+ var bounce = makeBounce(req, sock);
+ cb(req, bounce);
+
+ sock.on('end', function () {
+ req.destroy();
+ });
+ }
+ });
+
+ return server;
+};
+
+
+function makeBounce (req, res) {
+ var bounce = function (stream, opts) {
+ var rs = req.createRawStream();
+ var ws = res.createRawStream && res.createRawStream() || res;
+
+ if (!stream || !stream.write) {
+ opts = parseArgs(arguments);
+ stream = opts.stream;
+ }
+ if (!opts) opts = {};
+
+ if (!opts.headers) opts.headers = {};
+ if (!('x-forwarded-for' in opts.headers)) {
+ opts.headers['x-forwarded-for'] = req.connection.remoteAddress;
+ }
+ if (!('x-forwarded-port' in opts.headers)) {
+ var m = (req.headers.host || '').match(/:(\d+)/);
+ opts.headers['x-forwarded-port'] = m && m[1] || 80;
+ }
+ if (!('x-forwarded-proto' in opts.headers)) {
+ opts.headers['x-forwarded-proto'] =
+ req.connection.encrypted ? 'https' : 'http';
+ }
+
+ insertHeaders(rs.buffers, opts.headers);
+ if (opts.path) updatePath(rs.buffers, opts.path);
+
+ if (stream.writable) {
+ rs.pipe(stream, { end : false });
+ stream.pipe(ws);
+ }
+ else if (opts.emitter) {
+ opts.emitter.emit('drop', ws);
+ }
+
+ stream.on('error', function (err) {
+ if (stream.listeners('error').length === 1) {
+ // destroy the request and stream if nobody is listening
+ req.destroy();
+ stream.destroy();
+ }
+ });
+
+ stream.on('close', function () {
+ _onclose.forEach(function (fn) { fn() });
+ });
+
+ return stream;
+ };
+
+ var _onclose = [];
+ bounce._onclose = function (fn) {
+ _onclose.push(fn);
+ };
+
+ return bounce;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.