Browse files

integrating with ChildKiller

  • Loading branch information...
1 parent 0a09096 commit fa3d2535fc89f26b2e211335f47b32b4ec6974a6 @pghalliday committed Nov 19, 2012
Showing with 87 additions and 164 deletions.
  1. +2 −1 .gitignore
  2. +15 −7 README.md
  3. +3 −4 package.json
  4. +15 −66 src/LocalTunnel.js
  5. +0 −1 src/index.js
  6. +52 −75 test/src/LocalTunnel.js
  7. +0 −10 test/support/childProcess.js
View
3 .gitignore
@@ -1,2 +1,3 @@
node_modules
-.DS_Store
+.DS_Store
+npm-debug.log
View
22 README.md
@@ -6,7 +6,6 @@ Node.js wrapper for the localtunnel ruby client
## Features
- 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 stopped before started
- should error if started when already running
@@ -29,12 +28,21 @@ npm install node-localtunnel
var LocalTunnel = require('node-localtunnel');
var localTunnel = new LocalTunnel(8080);
-localTunnel.on('error', function(error) {
- console.log(error);
-});
-localTunnel.start(function(hostname) {
- // Now forwarding to local port 8080 through localtunnel.com
- // The assigned hostname is given in the hostname parameter
+localTunnel.start(function(error, hostname) {
+ if (error) {
+ console.log(error);
+ } else {
+ // Now forwarding to local port 8080 through localtunnel.com
+ // The assigned hostname is given in the hostname parameter
+
+ localTunnel.stop(function(error) {
+ if (error) {
+ console.log(error);
+ } else {
+ // tunnel has stopped
+ }
+ });
+ }
});
```
View
7 package.json
@@ -21,16 +21,15 @@
"url": "https://github.com/pghalliday/node-localtunnel/blob/master/LICENSE-MIT"
}
],
- "main": "src/index.js",
+ "main": "src/LocalTunnel.js",
"engines": {
"node": ">= 0.8.12"
},
"scripts": {
"test": "grunt"
},
- "dependencies": {},
- "optionalDependencies": {
- "pty.js": "0.1.2"
+ "dependencies": {
+ "ChildKiller": "https://github.com/pghalliday/ChildKiller/archive/master.tar.gz"
},
"devDependencies": {
"grunt": "0.3.17",
View
81 src/LocalTunnel.js
@@ -1,74 +1,23 @@
var util = require('util'),
- EventEmitter = require('events').EventEmitter;
+ ChildKiller = require('ChildKiller');
function LocalTunnel(port, binary) {
- var self = this,
- child,
- started = false;
-
- if (!binary) {
- binary = 'localtunnel';
- }
-
- 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]);
- }
- });
- }
- };
+ binary = binary || 'localtunnel';
+ ChildKiller.call(
+ this,
+ binary,
+ [port],
+ new RegExp('[a-z0-9]{4}\\.localtunnel\\.com')
+ );
- self.stop = function(callback) {
- if (!started) {
- self.emit('error', new Error('localtunnel not active'));
- } else {
- self.once('stopped', callback);
- child.kill();
- }
+ this.superStart = this.start;
+ this.start = function(callback) {
+ this.superStart(function(error, matched) {
+ var hostname = matched ? matched[0] : hostname;
+ callback(error, hostname);
+ });
};
}
-util.inherits(LocalTunnel, EventEmitter);
+util.inherits(LocalTunnel, ChildKiller);
module.exports = LocalTunnel;
View
1 src/index.js
@@ -1 +0,0 @@
-module.exports = require('./LocalTunnel');
View
127 test/src/LocalTunnel.js
@@ -1,47 +1,28 @@
var expect = require('expect.js'),
LocalTunnel = require('../../'),
- http = require('http'),
- fork = require('child_process').fork;
+ http = require('http');
var PORT = 8080;
var TEST_RESPONSE = "This is a test";
-var LOCALTUNNEL_NOT_FOUND_RESPONSE = "Not found";
describe('LocalTunnel', function() {
- it('should error if the binary does not exist', function(done) {
- var localTunnel = new LocalTunnel(PORT, 'blahblah');
- localTunnel.on('error', function(error) {
- expect(error.message).to.contain('localtunnel failed to start');
- done();
- });
- 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();
+ var server;
+
+ before(function(done) {
+ server = http.createServer(function(request, response) {
+ response.end(TEST_RESPONSE);
});
- localTunnel.stop(function() {
- expect().fail('should not get stopped event');
- });
+ server.listen(PORT, done);
});
- it('should start the localtunnel client', function(done) {
+ it('should start and stop the localtunnel client', function(done) {
this.timeout(10000);
var localTunnel = new LocalTunnel(PORT);
- localTunnel.on('error', function(error) {
- expect().fail('Error encountered starting the tunnel:\n' + error);
- });
- localTunnel.start(function(hostname) {
- expect(hostname).to.contain('localtunnel.com');
- var server = http.createServer(function(request, response) {
- response.end(TEST_RESPONSE);
- });
- server.listen(PORT, function() {
+ localTunnel.start(function(error, hostname) {
+ if (error) {
+ expect().fail('Error encountered starting the tunnel:\n' + error);
+ } else {
+ expect(hostname).to.contain('localtunnel.com');
http.get({
hostname: hostname
}, function(response) {
@@ -53,63 +34,59 @@ describe('LocalTunnel', function() {
});
response.on('end', function() {
expect(responseData).to.equal(TEST_RESPONSE);
-
- server.close(function() {
- localTunnel.stop(done);
+ localTunnel.stop(function(error) {
+ if (error) {
+ expect().fail('Error encountered stopping the tunnel:\n' + error);
+ } else {
+ done();
+ }
});
});
});
- });
+ }
});
});
- it('should error if started when already running', function(done) {
- this.timeout(10000);
- var localTunnel = new LocalTunnel(PORT);
- function tempErrorHandler(error) {
- expect().fail('Error encountered starting the tunnel:\n' + error);
- }
- 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 error if the binary does not exist', function(done) {
+ var localTunnel = new LocalTunnel(PORT, 'blahblah');
+ localTunnel.start(function(error, hostname) {
+ expect(error.message).to.contain('child failed to start');
+ expect(hostname).to.not.be.ok();
+ done();
});
});
- 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);
- var child = fork('./test/support/childProcess.js', [PORT]);
- child.on('message', function(message) {
- if (message.error) {
- expect().fail('Error encountered starting the tunnel:\n' + message.error);
- child.on('exit', done);
+ var localTunnel = new LocalTunnel(PORT);
+ localTunnel.start(function(error, hostname) {
+ if (error) {
+ expect().fail('Error encountered starting the tunnel:\n' + error);
} else {
- expect(message.hostname).to.contain('localtunnel.com');
- child.on('exit', function(code, signal) {
- var server = http.createServer(function(request, response) {
- response.end(TEST_RESPONSE);
- });
- server.listen(PORT, function() {
- http.get({
- hostname: message.hostname
- }, function(response) {
- expect(response.statusCode).to.equal(501);
- response.on('end', function() {
- server.close(done);
- });
- });
+ localTunnel.start(function(error, hostname) {
+ expect(error.message).to.be('child already started');
+ expect(hostname).to.not.be.ok();
+ localTunnel.stop(function(error) {
+ if (error) {
+ expect().fail('Error encountered stopping the tunnel:\n' + error);
+ } else {
+ done();
+ }
});
});
}
- child.kill();
});
});
+
+ after(function(done) {
+ server.close(done);
+ });
});
View
10 test/support/childProcess.js
@@ -1,10 +0,0 @@
-var LocalTunnel = require('../../');
-
-var localTunnel = new LocalTunnel(process.argv[2]);
-localTunnel.on('error', function(error) {
- process.send({error: error.toString()});
-});
-localTunnel.start(function(hostname) {
- process.send({hostname: hostname});
-});
-

0 comments on commit fa3d253

Please sign in to comment.