remove client components

* devDep localtunnel module for client
* update readme for server info
This commit is contained in:
Roman Shtylman
2013-06-16 18:46:29 -04:00
parent 0568ae0bef
commit a6ec239a27
7 changed files with 15 additions and 244 deletions

View File

@@ -1,30 +1,10 @@
# localtunnel [![Build Status](https://secure.travis-ci.org/shtylman/localtunnel.png)](http://travis-ci.org/shtylman/localtunnel) #
# localtunnel-server [![Build Status](https://secure.travis-ci.org/shtylman/localtunnel-server.png)](http://travis-ci.org/shtylman/localtunnel-serer) #
localtunnel exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.
Great for working with browser testing tools like browserling or external api callback services like twilio which require a public url for callbacks.
This repo is the server component. If you are just looking for the CLI localtunnel app, see (https://github.com/shtylman/localtunnel)
## installation ##
```
npm install -g localtunnel
```
This will install the localtunnel module globally and add the 'lt' client cli tool to your PATH.
## use ##
Super Easy! Assuming your local server is running on port 8000, just use the ```lt``` command to start the tunnel.
```
lt --port 8000
```
Thats it! It will connect to the tunnel server, setup the tunnel, and tell you what url to use for your testing. This url will remain active for the duration of your session; so feel free to share it with others for happy fun time!
You can restart your local server all you want, ```lt``` is smart enough to detect this and reconnect once it is back.
### custom server
## overview ##
The default localtunnel client connects to the ```localtunnel.me``` server. You can however easily setup and run your own server. In order to run your own localtunnel server you must ensure that your server can meet the following requirements:
@@ -37,7 +17,7 @@ The above are important as the client will ask the server for a subdomain under
```shell
// pick a place where the files will live
git clone git://github.com/shtylman/localtunnel.git
git clone git://github.com/shtylman/localtunnel-server.git
cd localtunnel
npm install
@@ -57,28 +37,3 @@ lt --host http://sub.example.tld:1234 --port 9000
You will be assigned a url similar to ```qdci.sub.example.com:1234```
If your server is being a reverse proxy (i.e. nginx) and is able to listen on port 80, then you do not need the ```:1234``` part of the hostname for the ```lt``` client
## API ##
The localtunnel client is also usable through an API (test integration, automation, etc)
```javascript
var lt_client = require('localtunnel').client;
var client = lt_client.connect({
// the localtunnel server
host: 'http://localtunnel.me',
// your local application port
port: 12345
});
// when your are assigned a url
client.on('url', function(url) {
// you can now make http requests to the url
// they will be proxied to your local server on port [12345]
});
client.on('error', function(err) {
// uh oh!
});
```

View File

@@ -1,34 +0,0 @@
#!/usr/bin/env node
var lt_client = require(__dirname + '/../client');
var argv = require('optimist')
.usage('Usage: $0 --port [num]')
.demand(['port'])
.options('host', {
default: 'http://localtunnel.me',
describe: 'upstream server providing forwarding'
})
.options('subdomain', {
describe: 'request this subdomain'
})
.describe('port', 'internal http server port')
.argv;
var opt = {
host: argv.host,
port: argv.port,
subdomain: argv.subdomain,
}
var client = lt_client.connect(opt);
// only emitted when the url changes
client.on('url', function(url) {
console.log('your url is: %s', url);
});
client.on('error', function(err) {
console.error(err);
});
// vim: ft=javascript

142
client.js
View File

@@ -1,142 +0,0 @@
// builtin
var net = require('net');
var url = require('url');
var request = require('request');
var EventEmitter = require('events').EventEmitter;
// request upstream url and connection info
var request_url = function(params, cb) {
request(params, function(err, res, body) {
if (err) {
cb(err);
}
cb(null, body);
});
};
var connect = function(opt) {
var ev = new EventEmitter();
// local port
var local_port = opt.port;
var base_uri = opt.host + '/';
// optionally override the upstream server
var upstream = url.parse(opt.host);
// no subdomain at first, maybe use requested domain
var assigned_domain = opt.subdomain;
// connect to upstream given connection parameters
var tunnel = function (remote_host, remote_port) {
var remote_opt = {
host: remote_host,
port: remote_port
};
var local_opt = {
host: 'localhost',
port: local_port
};
var remote_attempts = 0;
(function conn(conn_had_error) {
if (conn_had_error) {
return;
}
if (++remote_attempts >= 3) {
console.error('localtunnel server offline - try again');
process.exit(-1);
}
// connection to localtunnel server
var remote = net.connect(remote_opt);
remote.once('error', function(err) {
if (err.code !== 'ECONNREFUSED') {
remote.emit('error', err);
}
// retrying connection to local server
setTimeout(conn, 1000);
});
function recon_local() {
remote.pause();
remote_attempts = 0;
// connection to local http server
var local = net.connect(local_opt);
local.once('error', function(err) {
if (err.code !== 'ECONNREFUSED') {
local.emit('error', err);
}
// retrying connection to local server
setTimeout(recon_local, 1000);
});
local.once('connect', function() {
remote.resume();
remote.pipe(local).pipe(remote, {end: false});
});
local.once('close', function(had_error) {
if (had_error) {
return;
}
recon_local();
});
}
remote.once('close', conn);
remote.once('connect', recon_local);
})();
};
var params = {
path: '/',
json: true
};
// where to quest
params.uri = base_uri + ((assigned_domain) ? assigned_domain : '?new');
// get an id from lt server and setup forwarding tcp connections
request_url(params, function(err, body) {
if (err) {
ev.emit('error', new Error('tunnel server not available: %s, retry 1s', err.message));
// retry interval for id request
return setTimeout(function() {
connect_proxy(opt);
}, 1000);
}
// our assigned hostname and tcp port
var port = body.port;
var host = upstream.hostname;
// store the id so we can try to get the same one
assigned_domain = body.id;
var max_conn = body.max_conn_count || 1;
for (var count = 0 ; count < max_conn ; ++count) {
tunnel(host, port);
}
ev.emit('url', body.url);
});
return ev;
};
module.exports.connect = connect;

View File

@@ -1,2 +0,0 @@
module.exports.client = require('./client');
module.exports.server = require('./server');

View File

@@ -1,31 +1,25 @@
{
"author": "Roman Shtylman <shtylman@gmail.com>",
"name": "localtunnel",
"name": "localtunnel-server",
"description": "expose localhost to the world",
"version": "0.0.4",
"repository": {
"type": "git",
"url": "git://github.com/shtylman/localtunnel.git"
"url": "git://github.com/shtylman/localtunnel-server.git"
},
"dependencies": {
"request": "2.11.4",
"book": "1.2.0",
"optimist": "0.3.4",
"http-raw": "1.1.0"
"http-raw": "1.1.0",
"debug": "0.7.2"
},
"devDependencies": {
"mocha": "1.6.0"
},
"optionalDependencies": {},
"engines": {
"node": "*"
"mocha": "1.6.0",
"localtunnel": "0.0.4"
},
"scripts": {
"test": "mocha --ui qunit -- test",
"start": "./bin/server"
},
"bin": {
"lt": "./bin/client"
},
"main": "./index.js"
}
}

View File

@@ -2,8 +2,8 @@ var http = require('http');
var url = require('url');
var assert = require('assert');
var localtunnel_server = require('../').server();
var localtunnel_client = require('../').client;
var localtunnel_server = require('../server')();
var localtunnel_client = require('localtunnel').client;
test('setup localtunnel server', function(done) {
localtunnel_server.listen(3000, function() {

View File

@@ -2,11 +2,11 @@ var http = require('http');
var url = require('url');
var assert = require('assert');
var localtunnel_server = require('../').server({
var localtunnel_server = require('../server')({
max_tcp_sockets: 1
});
var localtunnel_client = require('../').client;
var localtunnel_client = require('localtunnel').client;
var server;