Skip to content

Commit

Permalink
integrating with ChildKiller
Browse files Browse the repository at this point in the history
  • Loading branch information
pghalliday committed Nov 19, 2012
1 parent 0a09096 commit fa3d253
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 164 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Original file line Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules node_modules
.DS_Store .DS_Store
npm-debug.log
22 changes: 15 additions & 7 deletions README.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Node.js wrapper for the localtunnel ruby client
## Features ## Features


- should start the localtunnel client - should start the localtunnel client
- should stop the localtunnel client when the process exits
- should error if the binary does not exist - should error if the binary does not exist
- should error if stopped before started - should error if stopped before started
- should error if started when already running - should error if started when already running
Expand All @@ -29,12 +28,21 @@ npm install node-localtunnel
var LocalTunnel = require('node-localtunnel'); var LocalTunnel = require('node-localtunnel');


var localTunnel = new LocalTunnel(8080); var localTunnel = new LocalTunnel(8080);
localTunnel.on('error', function(error) { localTunnel.start(function(error, hostname) {
console.log(error); if (error) {
}); console.log(error);
localTunnel.start(function(hostname) { } else {
// Now forwarding to local port 8080 through localtunnel.com // Now forwarding to local port 8080 through localtunnel.com
// The assigned hostname is given in the hostname parameter // The assigned hostname is given in the hostname parameter

localTunnel.stop(function(error) {
if (error) {
console.log(error);
} else {
// tunnel has stopped
}
});
}
}); });
``` ```


Expand Down
7 changes: 3 additions & 4 deletions package.json
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@
"url": "https://github.com/pghalliday/node-localtunnel/blob/master/LICENSE-MIT" "url": "https://github.com/pghalliday/node-localtunnel/blob/master/LICENSE-MIT"
} }
], ],
"main": "src/index.js", "main": "src/LocalTunnel.js",
"engines": { "engines": {
"node": ">= 0.8.12" "node": ">= 0.8.12"
}, },
"scripts": { "scripts": {
"test": "grunt" "test": "grunt"
}, },
"dependencies": {}, "dependencies": {
"optionalDependencies": { "ChildKiller": "https://github.com/pghalliday/ChildKiller/archive/master.tar.gz"
"pty.js": "0.1.2"
}, },
"devDependencies": { "devDependencies": {
"grunt": "0.3.17", "grunt": "0.3.17",
Expand Down
81 changes: 15 additions & 66 deletions src/LocalTunnel.js
Original file line number Original file line Diff line number Diff line change
@@ -1,74 +1,23 @@
var util = require('util'), var util = require('util'),
EventEmitter = require('events').EventEmitter; ChildKiller = require('ChildKiller');


function LocalTunnel(port, binary) { function LocalTunnel(port, binary) {
var self = this, binary = binary || 'localtunnel';
child, ChildKiller.call(
started = false; this,

binary,
if (!binary) { [port],
binary = 'localtunnel'; new RegExp('[a-z0-9]{4}\\.localtunnel\\.com')
} );

process.on("exit", function(code, signal) {
if (child) {
child.kill(signal);
}
});

self.start = function(callback) {
if (started) {
self.emit('error', new Error('local tunnel already started'));
} else {
var stdoutData = '';
var stdout;

if (process.platform === 'win32') {
child = require('child_process').spawn('cmd', ['/s', '/c', binary, port]);
stdout = child.stdout;
child.stderr.on('data', function(data) {
stdoutData += data;
});
} else {
stdout = child = require('pty.js').spawn(binary, [port], {
name: 'localtunnel',
cols: 80,
rows: 30
});
}

child.on('exit', function(code, signal) {
child = null;
if (!started) {
self.emit('error', new Error('localtunnel failed to start:\n' + stdoutData));
} else {
started = false;
self.emit('stopped');
}
});

stdout.setEncoding();
stdout.on('data', function(data) {
stdoutData += data.toString();
var match = stdoutData.match(/[a-z0-9]{4}\.localtunnel\.com/g);
if (match && !started) {
started = true;
self.once('started', callback);
self.emit('started', match[0]);
}
});
}
};


self.stop = function(callback) { this.superStart = this.start;
if (!started) { this.start = function(callback) {
self.emit('error', new Error('localtunnel not active')); this.superStart(function(error, matched) {
} else { var hostname = matched ? matched[0] : hostname;
self.once('stopped', callback); callback(error, hostname);
child.kill(); });
}
}; };
} }
util.inherits(LocalTunnel, EventEmitter); util.inherits(LocalTunnel, ChildKiller);


module.exports = LocalTunnel; module.exports = LocalTunnel;
1 change: 0 additions & 1 deletion src/index.js

This file was deleted.

127 changes: 52 additions & 75 deletions test/src/LocalTunnel.js
Original file line number Original file line Diff line number Diff line change
@@ -1,47 +1,28 @@
var expect = require('expect.js'), var expect = require('expect.js'),
LocalTunnel = require('../../'), LocalTunnel = require('../../'),
http = require('http'), http = require('http');
fork = require('child_process').fork;


var PORT = 8080; var PORT = 8080;
var TEST_RESPONSE = "This is a test"; var TEST_RESPONSE = "This is a test";
var LOCALTUNNEL_NOT_FOUND_RESPONSE = "Not found";


describe('LocalTunnel', function() { describe('LocalTunnel', function() {
it('should error if the binary does not exist', function(done) { var server;
var localTunnel = new LocalTunnel(PORT, 'blahblah');
localTunnel.on('error', function(error) { before(function(done) {
expect(error.message).to.contain('localtunnel failed to start'); server = http.createServer(function(request, response) {
done(); response.end(TEST_RESPONSE);
});
localTunnel.start(function(hostname) {
expect().fail('should not get started event');
});
});

it('should error if stopped before started', function(done) {
var localTunnel = new LocalTunnel(PORT);
localTunnel.on('error', function(error) {
expect(error.message).to.be('localtunnel not active');
done();
}); });
localTunnel.stop(function() { server.listen(PORT, done);
expect().fail('should not get stopped event');
});
}); });


it('should start the localtunnel client', function(done) { it('should start and stop the localtunnel client', function(done) {
this.timeout(10000); this.timeout(10000);
var localTunnel = new LocalTunnel(PORT); var localTunnel = new LocalTunnel(PORT);
localTunnel.on('error', function(error) { localTunnel.start(function(error, hostname) {
expect().fail('Error encountered starting the tunnel:\n' + error); if (error) {
}); expect().fail('Error encountered starting the tunnel:\n' + error);
localTunnel.start(function(hostname) { } else {
expect(hostname).to.contain('localtunnel.com'); expect(hostname).to.contain('localtunnel.com');
var server = http.createServer(function(request, response) {
response.end(TEST_RESPONSE);
});
server.listen(PORT, function() {
http.get({ http.get({
hostname: hostname hostname: hostname
}, function(response) { }, function(response) {
Expand All @@ -53,63 +34,59 @@ describe('LocalTunnel', function() {
}); });
response.on('end', function() { response.on('end', function() {
expect(responseData).to.equal(TEST_RESPONSE); expect(responseData).to.equal(TEST_RESPONSE);

localTunnel.stop(function(error) {
server.close(function() { if (error) {
localTunnel.stop(done); expect().fail('Error encountered stopping the tunnel:\n' + error);
} else {
done();
}
}); });
}); });
}); });
}); }
}); });
}); });


it('should error if started when already running', function(done) { it('should error if the binary does not exist', function(done) {
this.timeout(10000); var localTunnel = new LocalTunnel(PORT, 'blahblah');
var localTunnel = new LocalTunnel(PORT); localTunnel.start(function(error, hostname) {
function tempErrorHandler(error) { expect(error.message).to.contain('child failed to start');
expect().fail('Error encountered starting the tunnel:\n' + error); expect(hostname).to.not.be.ok();
} done();
localTunnel.on('error', tempErrorHandler);
localTunnel.start(function(hostname) {
localTunnel.removeListener('error', tempErrorHandler);
localTunnel.on('error', function(error) {
expect(error.message).to.be('local tunnel already started');
localTunnel.stop(function(error) {
done(error);
});
});
localTunnel.start(function(hostname) {
expect().fail('should not get started event');
});
}); });
}); });


it('should stop the localtunnel client when the process exits', function(done) { it('should error if stopped before started', function(done) {
var localTunnel = new LocalTunnel(PORT);
localTunnel.stop(function(error) {
expect(error.message).to.be('child not started');
done();
});
});

it('should error if started when already running', function(done) {
this.timeout(10000); this.timeout(10000);
var child = fork('./test/support/childProcess.js', [PORT]); var localTunnel = new LocalTunnel(PORT);
child.on('message', function(message) { localTunnel.start(function(error, hostname) {
if (message.error) { if (error) {
expect().fail('Error encountered starting the tunnel:\n' + message.error); expect().fail('Error encountered starting the tunnel:\n' + error);
child.on('exit', done);
} else { } else {
expect(message.hostname).to.contain('localtunnel.com'); localTunnel.start(function(error, hostname) {
child.on('exit', function(code, signal) { expect(error.message).to.be('child already started');
var server = http.createServer(function(request, response) { expect(hostname).to.not.be.ok();
response.end(TEST_RESPONSE); localTunnel.stop(function(error) {
}); if (error) {
server.listen(PORT, function() { expect().fail('Error encountered stopping the tunnel:\n' + error);
http.get({ } else {
hostname: message.hostname done();
}, function(response) { }
expect(response.statusCode).to.equal(501);
response.on('end', function() {
server.close(done);
});
});
}); });
}); });
} }
child.kill();
}); });
}); });

after(function(done) {
server.close(done);
});
}); });
10 changes: 0 additions & 10 deletions test/support/childProcess.js

This file was deleted.

0 comments on commit fa3d253

Please sign in to comment.