12 Commits

Author SHA1 Message Date
Roman Shtylman
9a38b8de0f v1.9.0 2018-04-03 22:36:17 -07:00
Roman Shtylman
c524872323 update History.md 2018-04-03 22:20:39 -07:00
Roman Shtylman
2372ec22cc add _request_ event to print basic request information 2018-04-03 22:16:32 -07:00
Jonas Finnemann Jensen
db22a4efe0 README: add Reference to go-localtunnel (#206) 2018-04-03 22:03:18 -07:00
Roman Shtylman
610484b9d7 ci: add node 8 and 9 for testing 2018-04-02 21:41:47 -07:00
Roman Shtylman
86deca52f2 add yarn.lock 2018-04-01 20:42:45 -07:00
Jimmie
cb3441a339 Add ability to specify env variables (#161)
Update yargs dependency to enable the new functionality.
2018-04-01 20:41:53 -07:00
Daniel Kezerashvili
32fd1fdcbd Add basic request logging functionality (#178) 2018-04-01 20:36:49 -07:00
Roman Shtylman
14cac6f6c8 Add LICENSE 2018-04-01 20:34:37 -07:00
Ricardo Rosales
1f33d4992d Fix host default value message for CLI help text (#211)
per https://github.com/localtunnel/localtunnel/blob/master/lib/Tunnel.js#L17
2018-01-07 10:14:27 -08:00
C. K. Tang
578dc9aaae Replace 'request' with 'axios' (#214) 2018-01-07 10:13:22 -08:00
Tom Osowski
4c136a265c Spelling Fix in Readme (#193) 2017-12-10 08:28:31 -08:00
9 changed files with 291 additions and 25 deletions

View File

@@ -2,3 +2,5 @@ language: node_js
node_js:
- "4"
- "6"
- "8"
- "9"

View File

@@ -1,3 +1,9 @@
# 1.9.0 (2018-04-03)
* Add _request_ event to Tunnel emitter
* Update yargs to support config via environment variables
* Add basic request logging when --print-requests argument is used
# 1.8.3 (2017-06-11)
* update request dependency

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Roman Shtylman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -33,6 +33,12 @@ Below are some common arguments. See `lt --help` for additional arguments
* `--subdomain` request a named subdomain on the localtunnel server (default is random characters)
* `--local-host` proxy to a hostname other than localhost
You may also specify arguments via env variables. E.x.
```
PORT=3000 lt
```
## API ##
The localtunnel client is also usable through an API (for test integration, automation, etc)
@@ -59,7 +65,7 @@ tunnel.on('close', function() {
### opts
* `subdomain` A *string* value requesting a specific subdomain on the proxy server. **Note** You may not actually receive this name depending on availablily.
* `subdomain` A *string* value requesting a specific subdomain on the proxy server. **Note** You may not actually receive this name depending on availability.
* `local_host` Proxy to this hostname instead of `localhost`. This will also cause the `Host` header to be re-written to this value in proxied requests.
### Tunnel
@@ -68,6 +74,7 @@ The `tunnel` instance returned to your callback emits the following events
|event|args|description|
|----|----|----|
|request|info|fires when a request is processed by the tunnel, contains _method_ and _path_ fields|
|error|err|fires when an error happens on the tunnel|
|close||fires when the tunnel has closed|
@@ -83,6 +90,8 @@ Clients in other languages
*go* [gotunnelme](https://github.com/NoahShen/gotunnelme)
*go* [go-localtunnel](https://github.com/localtunnel/go-localtunnel)
## server ##
See [localtunnel/server](//github.com/localtunnel/server) for details on the server that powers localtunnel.

View File

@@ -4,10 +4,11 @@ var open_url = require('openurl');
var argv = require('yargs')
.usage('Usage: $0 --port [num] <options>')
.env(true)
.option('h', {
alias: 'host',
describe: 'Upstream server providing forwarding',
default: 'http://localtunnel.me'
default: 'https://localtunnel.me',
})
.option('s', {
alias: 'subdomain',
@@ -25,7 +26,11 @@ var argv = require('yargs')
alias: 'port',
describe: 'Internal http server port',
})
.option('print-requests', {
describe: 'Print basic request info',
})
.require('port')
.boolean('print-requests')
.help('help', 'Show this help and exit')
.version(require('../package').version)
.argv;
@@ -43,6 +48,8 @@ var opt = {
subdomain: argv.subdomain,
};
const PrintRequests = argv['print-requests'];
lt_client(opt.port, opt, function(err, tunnel) {
if (err) {
throw err;
@@ -57,6 +64,12 @@ lt_client(opt.port, opt, function(err, tunnel) {
tunnel.on('error', function(err) {
throw err;
});
if (PrintRequests) {
tunnel.on('request', function(info) {
console.log(new Date().toString(), info.method, info.path);
});
}
});
// vim: ft=javascript

View File

@@ -1,6 +1,6 @@
var url = require('url');
var EventEmitter = require('events').EventEmitter;
var request = require('request');
var axios = require('axios');
var debug = require('debug')('localtunnel:client');
var TunnelCluster = require('./TunnelCluster');
@@ -26,8 +26,7 @@ Tunnel.prototype._init = function(cb) {
var opt = self._opt;
var params = {
path: '/',
json: true
responseType: 'json'
};
var base_uri = opt.host + '/';
@@ -39,26 +38,19 @@ Tunnel.prototype._init = function(cb) {
var assigned_domain = opt.subdomain;
// where to quest
params.uri = base_uri + ((assigned_domain) ? assigned_domain : '?new');
var uri = base_uri + ((assigned_domain) ? assigned_domain : '?new');
(function get_url() {
request(params, function(err, res, body) {
if (err) {
// TODO (shtylman) don't print to stdout?
console.log('tunnel server offline: ' + err.message + ', retry 1s');
return setTimeout(get_url, 1000);
}
if (res.statusCode !== 200) {
var err = new Error((body && body.message) || 'localtunnel server returned an error, please try again');
axios.get(uri, params)
.then(function(res){
var body = res.data;
if (res.status !== 200) {
var err = new Error((body && body.message) || 'localtunnel server returned an error, please try again');
return cb(err);
}
var port = body.port;
var host = upstream.hostname;
var max_conn = body.max_conn_count || 1;
cb(null, {
remote_host: upstream.hostname,
remote_port: body.port,
@@ -66,14 +58,19 @@ Tunnel.prototype._init = function(cb) {
url: body.url,
max_conn: max_conn
});
});
})
.catch(function(err){
// TODO (shtylman) don't print to stdout?
console.log('tunnel server offline: ' + err.message + ', retry 1s');
return setTimeout(get_url, 1000);
})
})();
};
Tunnel.prototype._establish = function(info) {
var self = this;
var opt = self._opt;
// increase max event listeners so that localtunnel consumers don't get
// warning messages as soon as they setup even one listener. See #71
self.setMaxListeners(info.max_conn + (EventEmitter.defaultMaxListeners || 10));
@@ -126,6 +123,10 @@ Tunnel.prototype._establish = function(info) {
tunnels.open();
});
tunnels.on('request', function(info) {
self.emit('request', info);
});
// establish as many tunnels as allowed
for (var count = 0 ; count < info.max_conn ; ++count) {
tunnels.open();

View File

@@ -113,6 +113,16 @@ TunnelCluster.prototype.open = function() {
});
}
remote.on('data', function(data) {
const match = data.toString().match(/^(\w+) (\S+)/);
if (match) {
self.emit('request', {
method: match[1],
path: match[2],
});
}
});
// tunnel is considered open when remote connects
remote.once('connect', function() {
self.emit('open', remote);

View File

@@ -2,17 +2,17 @@
"author": "Roman Shtylman <shtylman@gmail.com>",
"name": "localtunnel",
"description": "expose localhost to the world",
"version": "1.8.3",
"version": "1.9.0",
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/localtunnel/localtunnel.git"
},
"dependencies": {
"request": "2.81.0",
"yargs": "3.29.0",
"axios": "0.17.1",
"debug": "2.6.8",
"openurl": "1.1.1"
"openurl": "1.1.1",
"yargs": "6.6.0"
},
"devDependencies": {
"mocha": "~1.17.0"
@@ -24,4 +24,4 @@
"lt": "./bin/client"
},
"main": "./client.js"
}
}

204
yarn.lock Normal file
View File

@@ -0,0 +1,204 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
axios@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d"
dependencies:
follow-redirects "^1.2.5"
is-buffer "^1.1.5"
camelcase@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
cliui@^3.0.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi "^2.0.0"
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
commander@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06"
commander@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.0.0.tgz#d1b86f901f8b64bd941bdeadaf924530393be928"
debug@*, debug@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
ms "2.0.0"
debug@2.6.8:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
ms "2.0.0"
decamelize@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
diff@1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/diff/-/diff-1.0.7.tgz#24bbb001c4a7d5522169e7cabdb2c2814ed91cf4"
follow-redirects@^1.2.5:
version "1.4.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.4.1.tgz#d8120f4518190f55aac65bb6fc7b85fcd666d6aa"
dependencies:
debug "^3.1.0"
glob@3.2.3:
version "3.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.3.tgz#e313eeb249c7affaa5c475286b0e115b59839467"
dependencies:
graceful-fs "~2.0.0"
inherits "2"
minimatch "~0.2.11"
graceful-fs@~2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-2.0.3.tgz#7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0"
growl@1.7.x:
version "1.7.0"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.7.0.tgz#de2d66136d002e112ba70f3f10c31cf7c350b2da"
inherits@2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
is-buffer@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
dependencies:
number-is-nan "^1.0.0"
jade@0.26.3:
version "0.26.3"
resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c"
dependencies:
commander "0.6.1"
mkdirp "0.3.0"
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
dependencies:
invert-kv "^1.0.0"
lru-cache@2:
version "2.7.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952"
minimatch@~0.2.11:
version "0.2.14"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a"
dependencies:
lru-cache "2"
sigmund "~1.0.0"
mkdirp@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e"
mkdirp@0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.5.tgz#de3e5f8961c88c787ee1368df849ac4413eca8d7"
mocha@~1.17.0:
version "1.17.1"
resolved "https://registry.yarnpkg.com/mocha/-/mocha-1.17.1.tgz#7f7671d68526d074b7bae660c9099f87e0ea1ccb"
dependencies:
commander "2.0.0"
debug "*"
diff "1.0.7"
glob "3.2.3"
growl "1.7.x"
jade "0.26.3"
mkdirp "0.3.5"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
openurl@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387"
os-locale@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
dependencies:
lcid "^1.0.0"
sigmund@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
dependencies:
ansi-regex "^2.0.0"
window-size@^0.1.2:
version "0.1.4"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876"
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
y18n@^3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
yargs@3.29.0:
version "3.29.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.29.0.tgz#1aab9660eae79d8b8f675bcaeeab6ee34c2cf69c"
dependencies:
camelcase "^1.2.1"
cliui "^3.0.3"
decamelize "^1.0.0"
os-locale "^1.4.0"
window-size "^0.1.2"
y18n "^3.2.0"