Skip to content

Commit

Permalink
feat: support to stream websocket request (#4)
Browse files Browse the repository at this point in the history
* feat: support to proxy ws request

* bugfix and refactor

* rename SocketResponse

* chore: update readme

* chore: update readme
  • Loading branch information
embbnux authored Apr 15, 2022
1 parent 7ce1d6f commit 4007a96
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 62 deletions.
55 changes: 33 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# Lite HTTP Tunnel

A HTTP Tunnel tool to help you expose local HTTP server behind a NAT or firewall to the internet. Inspired by [Ngrok](https://github.com/inconshreveable/ngrok).
A HTTP Tunnel tool to help you expose local HTTP/WebSocket server behind a NAT or firewall to the internet. Inspired by [Ngrok](https://github.com/inconshreveable/ngrok) and [node-http-proxy](https://github.com/http-party/node-http-proxy).

![http tunnel](https://user-images.githubusercontent.com/7036536/155876708-f30f4921-c8c8-463d-8917-c4f932d3b2e6.png)


## How it work

The tunnel is based on `WebSocket`. We have a `WebSocket` connection between the client and server to stream HTTP request from public server to your local server.
The tunnel is based on `WebSocket`. We have a `WebSocket` connection between the client and server to stream HTTP/WebSocket requests from public server to your local server.

## Usage

Expand All @@ -29,40 +28,53 @@ You can also generate JWT Token in your local by following code [here](https://g

### Setup Client

Please install `lite-http-tunnel` client in your local computer where it can access your local HTTP server.

```
$ npm i -g lite-http-tunnel
$ lite-http-tunnel -h
```

Config remote public server address:
#### Config remote public server address:

```
```shell
$ lite-http-tunnel config server https://your_web_host_domain
```

Config jwt token that you got from server:
#### Config jwt token that you got from server:

```
```shell
$ lite-http-tunnel config jwt your_jwt_token
```

Start client
#### Or With specified profile

```shell
$ lite-http-tunnel config server https://your_web_host_domain -p profile1
$ lite-http-tunnel config jwt your_jwt_token -p profile1
```

#### Start client

```shell
$ lite-http-tunnel start your_local_server_port
```
Please replace your_local_server_port with your local HTTP server port, eg: `3000`.

Please replace your_local_server_port with your local HTTP server port, eg: `8080`.

After that you can access your local HTTP server by access `your_public_server_domain`.

Change origin
#### Start with specified profile:

```shell
$ lite-http-tunnel start your_local_server_port -p profile1
```

#### Change origin to local server:

```shell
$ lite-http-tunnel start your_local_server_port -o localhost:5000
```

#### Change local server host:

```shell
$ lite-http-tunnel start your_local_server_port -h localhost1
```

## Multiple Clients

The server steams HTTP request to WebSocket connection which has same host value in request headers.
Expand All @@ -74,15 +86,15 @@ For example, you have `https://app1.test.com` and `https://app2.test.com` for th
In client 1:

```
$ lite-http-tunnel config server https://app1.test.com -p app1
$ lite-http-tunnel start your_local_server_port -p app1
$ lite-http-tunnel config server https://app1.test.com -p profile1
$ lite-http-tunnel start your_local_server_port -p profile1
```

In client 2:

```
$ lite-http-tunnel config server https://app2.test.com -p app2
$ lite-http-tunnel start your_local_server_port -p app2
$ lite-http-tunnel config server https://app2.test.com -p profile2
$ lite-http-tunnel start your_local_server_port -p profile2
```

## Related
Expand All @@ -93,4 +105,3 @@ A introduce article: [Building a HTTP Tunnel with WebSocket and Node.JS](https:/

- [ ] Add tests
- [ ] Support multiple clients based on request path prefix
- [ ] Support to stream WebSocket request
49 changes: 43 additions & 6 deletions lib.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

const { Writable, Readable } = require('stream');
const { Writable, Duplex } = require('stream');

class SocketRequest extends Writable {
class TunnelRequest extends Writable {
constructor({ socket, requestId, request }) {
super();
this._socket = socket;
Expand Down Expand Up @@ -42,7 +42,7 @@ class SocketRequest extends Writable {
}
}

class SocketResponse extends Readable {
class TunnelResponse extends Duplex {
constructor({ socket, responseId }) {
super();
this._socket = socket;
Expand All @@ -51,7 +51,12 @@ class SocketResponse extends Readable {
if (this._responseId === responseId) {
this._socket.off('response', onResponse);
this._socket.off('request-error', onRequestError);
this.emit('response', data.statusCode, data.statusMessage, data.headers);
this.emit('response', {
statusCode: data.statusCode,
statusMessage: data.statusMessage,
headers: data.headers,
httpVersion: data.httpVersion,
});
}
}
const onResponsePipe = (responseId, data) => {
Expand Down Expand Up @@ -109,7 +114,39 @@ class SocketResponse extends Readable {
}

_read(size) {}

_write(chunk, encoding, callback) {
this._socket.emit('response-pipe', this._responseId, chunk);
this._socket.conn.once('drain', () => {
callback();
});
}

_writev(chunks, callback) {
this._socket.emit('response-pipes', this._responseId, chunks);
this._socket.conn.once('drain', () => {
callback();
});
}

_final(callback) {
this._socket.emit('response-pipe-end', this._responseId);
this._socket.conn.once('drain', () => {
callback();
});
}

_destroy(e, callback) {
if (e) {
this._socket.emit('response-pipe-error', this._responseId, e && e.message);
this._socket.conn.once('drain', () => {
callback();
});
return;
}
callback();
}
}

exports.SocketRequest = SocketRequest;
exports.SocketResponse = SocketResponse;
exports.TunnelRequest = TunnelRequest;
exports.TunnelResponse = TunnelResponse;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lite-http-tunnel-server",
"version": "0.0.1",
"version": "0.1.0",
"main": "server.js",
"engines": {
"node": ">=14.0"
Expand Down
Loading

0 comments on commit 4007a96

Please sign in to comment.