npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-local-tunnel

v0.1.8

Published

A live secure tunnel redirect public requests to your own local server befind a NAT or firewall

Downloads

24

Readme

Node-Local-Tunnel [NLT]

=========================

This is a live secure tunnel(a lightweight nodejs version of ngrok(https://ngrok.com) redirect public requests to your own local server behind a NAT or firewall, simplify mobile device testing, very useful to debug production server on your own mechine

Why & How it works

Sometimes, we have to test or live add/del things on a public server with public domain (e.g development with public services [Wechat, Weibo, Alipay..], or mobile device testing behind NAT or firewall), which usually requires server reloading, proxy configuration, ssh login, re-deploying .... It will be much simpler if we could proxy the requests from public server to our own local mechine, and testing/debuging on the local server. But if you are behind NAT or firewall(e.g secure network, mobile netwrok), the normal proxy engine(e.g. nginx) will not work. A principle to achieve that is setup a tunnel/connection to help you relay packages between the public server and your local server.

The ngrok(https://ngrok.com) is a well-known public service to do this. But it is a general native server written in c/c++, powerful but little heavy in most of cases. Besides, the public service is blocked in China, and setup a private ngrok server is hard and complex.

The NLT[node-local-tunnel] is a pure nodejs module, only few lines, it will setup up a live secure tunnel (by websocket), catch all/part[target ones] of the requests from one server, live redirect/relay them to a local server. Easy use, easy configure.

Installing

This is a typical nodejs module, so just install by npm

# npm install node-local-tunnel

Try examples in /test(https://github.com/lslzl3000/node-local-tunnel/tree/master/test), see how it works to redirect requests to your local server

How to use

on public/production Server

    var app = require('express')(), // work with express
    
    // on remote server, init NLT first
    var NLTunnel = require('node-local-tunnel');
    NLTunnel.init();  // init the tunnel server
    
    // then hannel all logic requests by app.use
    app.use( NLTunnel.server() );

    // You can also apply routers to relay specific requests, e.g.
    // app.get('/foo', NLTunnel.server() ); // only relay /foo with 'GET' request 
    
    // better use NLT before other middleware
    var	bodyParser = require('body-parser'),
		  compression = require('compression');
    ...
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded());
    app.use(compression());
    app.use(express.static('assets/')); // if you don't want relay static files, put this line before NLT
    ...

    app.use('/someurl', function(req, res, next){
      // Your codes ...
    });
    .......
    app.listen(80);

on local/dev Server

    var app = require('express')(), // work with express
    
    var NLTunnel = require('node-local-tunnel');
    var options = {
      remoteHost : 'your-public-server.com',
      localBase : 'http://localhost:3000'
    };
    NLTunnel.client(options); // just call client() somewhere with options, you are free to go
    
    var	bodyParser = require('body-parser'),
	compression = require('compression');
	...
	app.use(bodyParser.json());
    app.use(bodyParser.urlencoded());
	app.use(compression());
	app.use(express.static('assets/'));
	...

    app.use('/someurl', function(req, res, next){
      // Your codes ...
    });
    .......
    app.listen(3000);

options for public/production server

    var options = {
      port : 12345, // which port to setup the websocket server, 12345 by default
      auth : { // tunnel auth info, you have to setup the client with same obj to connect, null by default
        username : 'admin',
        passwork : '123456'
      },
      ssl : {	// give ssl cert if you want setup a ssl secure tunnel, null by default
        cert : fs.readFileSync('./ssl-cert.pem'),
        key : fs.readFileSync('./ssl-key.pem')
      }
    };
    NLTunnel.init(options);
    app.use( NLTunnel.server(options) );

options for local/dev server

    var options = {
      port : 12345, // remote NLT server port, 12345 by default
      remoteHost : 'public-server-domain',	// remote server hostname, e.g example.com
      localBase : 'http://localhost:3000', // local server base url
      path : [ '/foo' ],	// a filter to check req.url, set it empty if you want relay all requests
      filter : {	// a bypass to identify requests, only relay those who fit all values in req obj
        // some useful examples, set any target to match what you want from the request obj
        ip:'[127.0.0.1]', 	// match req.ip (hint. req.ip is a powered by Express, you may need to find ip in req.headers['x-forwarded-for'] || req.connection.remoteAddress || ... in other framework or pure Nodejs)
        hostname:'localhost', // match req.hostnaem, check from which host (same above, req.hostname is powered by Express, use headers.host in general way)
        'headers.user-agent':'[Chrome]' // check req.headers[user-agent], check if chrome
      },
      auth : { // auth info to connect to the relay server 
        username : 'admin',
        password: '123456'
      },
      ssl: false // true if server ssl enabled, false by default
    };
    NLTunnel.client(options) );

path & filter rules

NLT uses pure string to check target path or filter, but if the string packaged with '[]', it will be transger into Regex object to match the target, e.g.

path : [ '/foo', '/getOrder']

which means we only want req.url only equles to '/foo' or '/getOrder', but

path : [ '[/foo]', '[/getOrder/\\W+]']

means we want to relay all requests whose url matchs '/foo' (e.g. '/foo','/foolish','/foo/name'...) and '/getOrder/...' (e.g. '/getOrder/name', '/getOrder/:order_id')

The same rule apply with opionts.filter, e.g.

hostname : 'example.com' // means filter those hostname **equles to** 'example.com'
hostname : '[example.com]' // means filter those hostname **matchs** 'example.com', which also contains 'sub.example.com'

hint : req.hostname is powered by Express, you may find 'headers.host' in a general request

If you want to check sub-layer object value in req obj(e.g cookies or userAgent), just write it, e.g.

'headers.user-agent' : '[Chrome]' // check user-agent value in headers, match target words
'headers.cookie' :  '[login=true]' // check cookie value in headers, match target words

Useage tips

1 If you know how nodejs/express middleware works, you should know where to use NLT.server() in your codes

    app.use(NLT.server()) // global handle

    VS

    app.use('/someurl', NLT.server())  // handle specific url
    // handle before static middleware, which means also realy static files
    app.use(NLT.server())
    app.use(express.static()) 

    VS
  
    // handle after static, which means use static files on the remote server
    app.use(express.static())
    app.use(NLT.server()) 

2 Put NLT options in a config.js, make the main code clean and easy management

    ...
    var config = require('./config.js');
    var NLT = require('node-local-tunnel');
    ...
    NLT.init(config.NLT.server); // or NLT.server(config.NLT.server) 
    ...
    // or NLT.client(config.NLT.client);

3 You can easily code one js but run different params/env to start client/server mode

    ...
    if(process.env.DEV == true) // check whatever you want
      NLT.client(config.NLT.client); // init client in dev server
    else 
      NLT.init(config.NLT.server); // init NLT tunnel in public server
    ...

4 if you use nodejs cluster mode, you should put NLT.init()/NLT.client() in master, and put app.use(NLT.server()) in cluster

    ... 
    // setup NLT server in master
    if(cluster.isMaster){
      ...

      if(process.env.DEV)
        NLT.client(config.NLT.client); // init client in master
      else
        NLT.init(config.NLT.server); // init NLT tunnel

      ...
    }
    else{
      ...

      // user in public server
      if(!process.env.DEV)
        app.use(NLT.server(config.NLT.server));

      ...
    }
    ...

5 Certainly, you can use NLT as a standalone relay agent in a public server, and relay everything back to your own PC/laptop/.. where you want. See demos in /test(https://github.com/lslzl3000/node-local-tunnel/tree/master/test).

Limitation & work to do

This is a very simple module rightnow, I can't promise no bugs, please welcome to send issues.

Currently, this module will only work with one dev client(enough for most of cases, may update for multi-tunnels), if you try to connect with multiple dev clients, NLT will only relay requests between the latest one, put others on hlod.

Besides, the relay server only send four common values from req

url, including query strings
method, GET, PUT, POST, DELETE ...
body, form data append on POST/PUT ....
and headers, including user-agent, cookie, ETag ...

and send back four main values from dev server

statusCode, 200/404/302/500 ...
err, error messages from request
body, main response data
and headers, including set-cookie, encoding, ETag ....

Please welcome to make changes to enable more custom features (.e.g relay multi-part data) for this module.