pipenet 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.github/workflows/feature.yaml +39 -0
  2. package/.github/workflows/main.yaml +41 -0
  3. package/LICENSE +49 -0
  4. package/README.md +114 -0
  5. package/dist/HeaderHostTransformer.d.ts +11 -0
  6. package/dist/HeaderHostTransformer.d.ts.map +1 -0
  7. package/dist/HeaderHostTransformer.js +19 -0
  8. package/dist/HeaderHostTransformer.js.map +1 -0
  9. package/dist/Tunnel.d.ts +29 -0
  10. package/dist/Tunnel.d.ts.map +1 -0
  11. package/dist/Tunnel.js +132 -0
  12. package/dist/Tunnel.js.map +1 -0
  13. package/dist/TunnelCluster.d.ts +27 -0
  14. package/dist/TunnelCluster.d.ts.map +1 -0
  15. package/dist/TunnelCluster.js +101 -0
  16. package/dist/TunnelCluster.js.map +1 -0
  17. package/dist/cli.d.ts +3 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +161 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/pipenet.d.ts +17 -0
  22. package/dist/pipenet.d.ts.map +1 -0
  23. package/dist/pipenet.js +16 -0
  24. package/dist/pipenet.js.map +1 -0
  25. package/dist/pipenet.spec.d.ts +2 -0
  26. package/dist/pipenet.spec.d.ts.map +1 -0
  27. package/dist/pipenet.spec.js +67 -0
  28. package/dist/pipenet.spec.js.map +1 -0
  29. package/dist/server/Client.d.ts +20 -0
  30. package/dist/server/Client.d.ts.map +1 -0
  31. package/dist/server/Client.js +91 -0
  32. package/dist/server/Client.js.map +1 -0
  33. package/dist/server/Client.spec.d.ts +2 -0
  34. package/dist/server/Client.spec.d.ts.map +1 -0
  35. package/dist/server/Client.spec.js +117 -0
  36. package/dist/server/Client.spec.js.map +1 -0
  37. package/dist/server/ClientManager.d.ts +23 -0
  38. package/dist/server/ClientManager.d.ts.map +1 -0
  39. package/dist/server/ClientManager.js +64 -0
  40. package/dist/server/ClientManager.js.map +1 -0
  41. package/dist/server/ClientManager.spec.d.ts +2 -0
  42. package/dist/server/ClientManager.spec.d.ts.map +1 -0
  43. package/dist/server/ClientManager.spec.js +74 -0
  44. package/dist/server/ClientManager.spec.js.map +1 -0
  45. package/dist/server/TunnelAgent.d.ts +32 -0
  46. package/dist/server/TunnelAgent.d.ts.map +1 -0
  47. package/dist/server/TunnelAgent.js +110 -0
  48. package/dist/server/TunnelAgent.js.map +1 -0
  49. package/dist/server/TunnelAgent.spec.d.ts +2 -0
  50. package/dist/server/TunnelAgent.spec.d.ts.map +1 -0
  51. package/dist/server/TunnelAgent.spec.js +109 -0
  52. package/dist/server/TunnelAgent.spec.js.map +1 -0
  53. package/dist/server/index.d.ts +5 -0
  54. package/dist/server/index.d.ts.map +1 -0
  55. package/dist/server/index.js +5 -0
  56. package/dist/server/index.js.map +1 -0
  57. package/dist/server/server.d.ts +9 -0
  58. package/dist/server/server.d.ts.map +1 -0
  59. package/dist/server/server.js +129 -0
  60. package/dist/server/server.js.map +1 -0
  61. package/dist/server/server.spec.d.ts +2 -0
  62. package/dist/server/server.spec.d.ts.map +1 -0
  63. package/dist/server/server.spec.js +113 -0
  64. package/dist/server/server.spec.js.map +1 -0
  65. package/eslint.config.ts +28 -0
  66. package/package.json +73 -0
  67. package/src/HeaderHostTransformer.ts +29 -0
  68. package/src/Tunnel.ts +202 -0
  69. package/src/TunnelCluster.ts +166 -0
  70. package/src/cli.ts +204 -0
  71. package/src/pipenet.spec.ts +82 -0
  72. package/src/pipenet.ts +39 -0
  73. package/src/server/Client.spec.ts +139 -0
  74. package/src/server/Client.ts +114 -0
  75. package/src/server/ClientManager.spec.ts +90 -0
  76. package/src/server/ClientManager.ts +82 -0
  77. package/src/server/TunnelAgent.spec.ts +142 -0
  78. package/src/server/TunnelAgent.ts +135 -0
  79. package/src/server/index.ts +4 -0
  80. package/src/server/server.spec.ts +139 -0
  81. package/src/server/server.ts +171 -0
  82. package/src/types/human-readable-ids.d.ts +5 -0
  83. package/tsconfig.json +20 -0
  84. package/vitest.config.ts +10 -0
@@ -0,0 +1,39 @@
1
+ name: Run Tests
2
+ on:
3
+ pull_request:
4
+ branches:
5
+ - main
6
+ types:
7
+ - opened
8
+ - synchronize
9
+ - reopened
10
+ - ready_for_review
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ name: Test
15
+ strategy:
16
+ fail-fast: true
17
+ matrix:
18
+ node:
19
+ - 24
20
+ steps:
21
+ - name: Checkout repository
22
+ uses: actions/checkout@v4
23
+ with:
24
+ fetch-depth: 0
25
+ - uses: pnpm/action-setup@v4
26
+ with:
27
+ version: 9
28
+ - name: Setup NodeJS ${{ matrix.node }}
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: ${{ matrix.node }}
32
+ cache: "pnpm"
33
+ cache-dependency-path: "**/pnpm-lock.yaml"
34
+ - name: Install dependencies
35
+ run: pnpm install
36
+ - name: Run lint
37
+ run: pnpm lint
38
+ - name: Run tests
39
+ run: pnpm test
@@ -0,0 +1,41 @@
1
+ name: Release
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ jobs:
7
+ test:
8
+ environment: release
9
+ name: Test
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ issues: write
14
+ pull-requests: write
15
+ id-token: write
16
+ steps:
17
+ - name: setup repository
18
+ uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0
21
+ - uses: pnpm/action-setup@v4
22
+ with:
23
+ version: 9
24
+ - name: Setup NodeJS
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: 24
28
+ cache: "pnpm"
29
+ cache-dependency-path: "**/pnpm-lock.yaml"
30
+ - name: Install dependencies
31
+ run: pnpm install
32
+ - name: Run lint
33
+ run: pnpm lint
34
+ - name: Run tests
35
+ run: pnpm test
36
+ - name: Build
37
+ run: pnpm build
38
+ - name: Release
39
+ run: pnpm semantic-release
40
+ env:
41
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/LICENSE ADDED
@@ -0,0 +1,49 @@
1
+ The MIT License (MIT)
2
+ =====================
3
+
4
+ Copyright © 2026 Frank Fiegel (frank@glama.ai)
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the “Software”), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
26
+
27
+ ---
28
+
29
+ MIT License
30
+
31
+ Copyright (c) 2018 Roman Shtylman
32
+
33
+ Permission is hereby granted, free of charge, to any person obtaining a copy
34
+ of this software and associated documentation files (the "Software"), to deal
35
+ in the Software without restriction, including without limitation the rights
36
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
37
+ copies of the Software, and to permit persons to whom the Software is
38
+ furnished to do so, subject to the following conditions:
39
+
40
+ The above copyright notice and this permission notice shall be included in all
41
+ copies or substantial portions of the Software.
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
46
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
47
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
48
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
49
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # pipenet
2
+
3
+ pipenet 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.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install pipenet
9
+ # or
10
+ pnpm add pipenet
11
+ ```
12
+
13
+ ## API
14
+
15
+ The pipenet client is also usable through an API (for test integration, automation, etc)
16
+
17
+ ### pipenet(port [,options][,callback])
18
+
19
+ Creates a new pipenet tunnel to the specified local `port`. Will return a Promise that resolves once you have been assigned a public tunnel url. `options` can be used to request a specific `subdomain`. A `callback` function can be passed, in which case it won't return a Promise. This exists for backwards compatibility with the old Node-style callback API. You may also pass a single options object with `port` as a property.
20
+
21
+ ```js
22
+ import pipenet from 'pipenet';
23
+
24
+ const tunnel = await pipenet({ port: 3000 });
25
+
26
+ // the assigned public url for your tunnel
27
+ // i.e. https://abcdefgjhij.pipenet.me
28
+ tunnel.url;
29
+
30
+ tunnel.on('close', () => {
31
+ // tunnels are closed
32
+ });
33
+ ```
34
+
35
+ #### options
36
+
37
+ - `port` (number) [required] The local port number to expose through pipenet.
38
+ - `subdomain` (string) Request a specific subdomain on the proxy server. **Note** You may not actually receive this name depending on availability.
39
+ - `host` (string) URL for the upstream proxy server. Defaults to `https://pipenet.me`.
40
+ - `local_host` (string) Proxy to this hostname instead of `localhost`. This will also cause the `Host` header to be re-written to this value in proxied requests.
41
+ - `local_https` (boolean) Enable tunneling to local HTTPS server.
42
+ - `local_cert` (string) Path to certificate PEM file for local HTTPS server.
43
+ - `local_key` (string) Path to certificate key file for local HTTPS server.
44
+ - `local_ca` (string) Path to certificate authority file for self-signed certificates.
45
+ - `allow_invalid_cert` (boolean) Disable certificate checks for your local HTTPS server (ignore cert/key/ca options).
46
+
47
+ Refer to [tls.createSecureContext](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options) for details on the certificate options.
48
+
49
+ ### Tunnel
50
+
51
+ The `tunnel` instance returned to your callback emits the following events
52
+
53
+ | event | args | description |
54
+ | ------- | ---- | ------------------------------------------------------------------------------------ |
55
+ | request | info | fires when a request is processed by the tunnel, contains _method_ and _path_ fields |
56
+ | error | err | fires when an error happens on the tunnel |
57
+ | close | | fires when the tunnel has closed |
58
+
59
+ The `tunnel` instance has the following methods
60
+
61
+ | method | args | description |
62
+ | ------ | ---- | ---------------- |
63
+ | close | | close the tunnel |
64
+
65
+ ## Server
66
+
67
+ This package includes both the client and server components. You can run your own pipenet server.
68
+
69
+ ### Running the Server
70
+
71
+ ```bash
72
+ # Using the CLI
73
+ npx pipenet-server --port 3000
74
+
75
+ # Or programmatically
76
+ ```
77
+
78
+ ```js
79
+ import { createServer } from 'pipenet/server';
80
+
81
+ const server = createServer({
82
+ domain: 'tunnel.example.com', // Optional: custom domain
83
+ secure: false, // Optional: require HTTPS
84
+ landing: 'https://example.com', // Optional: landing page URL
85
+ max_tcp_sockets: 10, // Optional: max sockets per client
86
+ });
87
+
88
+ server.listen(3000, () => {
89
+ console.log('pipenet server listening on port 3000');
90
+ });
91
+ ```
92
+
93
+ ### Server Options
94
+
95
+ - `domain` (string) Custom domain for the tunnel server
96
+ - `secure` (boolean) Require HTTPS connections
97
+ - `landing` (string) URL to redirect root requests to
98
+ - `max_tcp_sockets` (number) Maximum number of TCP sockets per client (default: 10)
99
+
100
+ ### Server API Endpoints
101
+
102
+ - `GET /api/status` - Server status and tunnel count
103
+ - `GET /api/tunnels/:id/status` - Status of a specific tunnel
104
+ - `GET /:id` - Request a new tunnel with the specified ID
105
+
106
+ ## Acknowledgments
107
+
108
+ pipenet is based on [localtunnel](https://github.com/localtunnel/localtunnel), an open-source project by [@defunctzombie](https://github.com/defunctzombie). We are grateful for the foundation it provided.
109
+
110
+ Development of pipenet is sponsored by [glama.ai](https://glama.ai).
111
+
112
+ ## License
113
+
114
+ MIT
@@ -0,0 +1,11 @@
1
+ import { Transform, TransformCallback, TransformOptions } from 'stream';
2
+ export interface HeaderHostTransformerOptions extends TransformOptions {
3
+ host?: string;
4
+ }
5
+ export declare class HeaderHostTransformer extends Transform {
6
+ private host;
7
+ private replaced;
8
+ constructor(opts?: HeaderHostTransformerOptions);
9
+ _transform(data: Buffer, encoding: BufferEncoding, callback: TransformCallback): void;
10
+ }
11
+ //# sourceMappingURL=HeaderHostTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderHostTransformer.d.ts","sourceRoot":"","sources":["../src/HeaderHostTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAExE,MAAM,WAAW,4BAA6B,SAAQ,gBAAgB;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,qBAAsB,SAAQ,SAAS;IAClD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAU;gBAEd,IAAI,GAAE,4BAAiC;IAMnD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;CAWtF"}
@@ -0,0 +1,19 @@
1
+ import { Transform } from 'stream';
2
+ export class HeaderHostTransformer extends Transform {
3
+ host;
4
+ replaced;
5
+ constructor(opts = {}) {
6
+ super(opts);
7
+ this.host = opts.host || 'localhost';
8
+ this.replaced = false;
9
+ }
10
+ _transform(data, encoding, callback) {
11
+ callback(null, this.replaced
12
+ ? data
13
+ : data.toString().replace(/(\r\n[Hh]ost: )\S+/, (match, $1) => {
14
+ this.replaced = true;
15
+ return $1 + this.host;
16
+ }));
17
+ }
18
+ }
19
+ //# sourceMappingURL=HeaderHostTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderHostTransformer.js","sourceRoot":"","sources":["../src/HeaderHostTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuC,MAAM,QAAQ,CAAC;AAMxE,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAC1C,IAAI,CAAS;IACb,QAAQ,CAAU;IAE1B,YAAY,OAAqC,EAAE;QACjD,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,WAAW,CAAC;QACrC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,UAAU,CAAC,IAAY,EAAE,QAAwB,EAAE,QAA2B;QAC5E,QAAQ,CACN,IAAI,EACJ,IAAI,CAAC,QAAQ;YACX,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAU,EAAE,EAAE;gBAClE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;YACxB,CAAC,CAAC,CACP,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import { EventEmitter } from 'events';
2
+ import { TunnelCluster } from './TunnelCluster.js';
3
+ export interface TunnelOptions {
4
+ port?: number;
5
+ host?: string;
6
+ subdomain?: string;
7
+ local_host?: string;
8
+ local_https?: boolean;
9
+ local_cert?: string;
10
+ local_key?: string;
11
+ local_ca?: string;
12
+ allow_invalid_cert?: boolean;
13
+ headers?: Record<string, string>;
14
+ }
15
+ export declare class Tunnel extends EventEmitter {
16
+ opts: TunnelOptions;
17
+ closed: boolean;
18
+ clientId?: string;
19
+ url?: string;
20
+ cachedUrl?: string;
21
+ tunnelCluster?: TunnelCluster;
22
+ constructor(opts?: TunnelOptions);
23
+ private _getInfo;
24
+ private _init;
25
+ private _establish;
26
+ open(cb: (err?: Error) => void): void;
27
+ close(): void;
28
+ }
29
+ //# sourceMappingURL=Tunnel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tunnel.d.ts","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,EAAE,aAAa,EAAwB,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AA6BD,qBAAa,MAAO,SAAQ,YAAY;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;gBAEzB,IAAI,GAAE,aAAkB;IASpC,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,KAAK;IAoCb,OAAO,CAAC,UAAU;IAqDlB,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAmBrC,KAAK,IAAI,IAAI;CAId"}
package/dist/Tunnel.js ADDED
@@ -0,0 +1,132 @@
1
+ import { EventEmitter } from 'events';
2
+ import axios from 'axios';
3
+ import debug from 'debug';
4
+ import { TunnelCluster } from './TunnelCluster.js';
5
+ const log = debug('pipenet:client');
6
+ export class Tunnel extends EventEmitter {
7
+ opts;
8
+ closed;
9
+ clientId;
10
+ url;
11
+ cachedUrl;
12
+ tunnelCluster;
13
+ constructor(opts = {}) {
14
+ super();
15
+ this.opts = opts;
16
+ this.closed = false;
17
+ if (!this.opts.host) {
18
+ this.opts.host = 'https://pipenet.me';
19
+ }
20
+ }
21
+ _getInfo(body) {
22
+ const { id, ip, port, url, cached_url, max_conn_count } = body;
23
+ const { host, port: local_port, local_host } = this.opts;
24
+ const { local_https, local_cert, local_key, local_ca, allow_invalid_cert } = this.opts;
25
+ return {
26
+ name: id,
27
+ url,
28
+ cached_url,
29
+ max_conn: max_conn_count || 1,
30
+ remote_host: new URL(host).hostname,
31
+ remote_ip: ip,
32
+ remote_port: port,
33
+ local_port,
34
+ local_host,
35
+ local_https,
36
+ local_cert,
37
+ local_key,
38
+ local_ca,
39
+ allow_invalid_cert,
40
+ };
41
+ }
42
+ _init(cb) {
43
+ const opt = this.opts;
44
+ const getInfo = this._getInfo.bind(this);
45
+ const params = {
46
+ responseType: 'json',
47
+ headers: opt.headers || {},
48
+ };
49
+ const baseUri = `${opt.host}/`;
50
+ const assignedDomain = opt.subdomain;
51
+ const uri = baseUri + (assignedDomain || '?new');
52
+ const getUrl = () => {
53
+ axios
54
+ .get(uri, params)
55
+ .then((res) => {
56
+ const body = res.data;
57
+ log('got tunnel information', res.data);
58
+ if (res.status !== 200) {
59
+ const err = new Error(body?.message || 'pipenet server returned an error, please try again');
60
+ return cb(err);
61
+ }
62
+ cb(null, getInfo(body));
63
+ })
64
+ .catch((err) => {
65
+ log(`tunnel server offline: ${err.message}, retry 1s`);
66
+ setTimeout(getUrl, 1000);
67
+ });
68
+ };
69
+ getUrl();
70
+ }
71
+ _establish(info) {
72
+ this.setMaxListeners(info.max_conn + (EventEmitter.defaultMaxListeners || 10));
73
+ this.tunnelCluster = new TunnelCluster(info);
74
+ this.tunnelCluster.once('open', () => {
75
+ this.emit('url', info.url);
76
+ });
77
+ this.tunnelCluster.on('error', (err) => {
78
+ log('got socket error', err.message);
79
+ this.emit('error', err);
80
+ });
81
+ let tunnelCount = 0;
82
+ this.tunnelCluster.on('open', (tunnel) => {
83
+ tunnelCount++;
84
+ log('tunnel open [total: %d]', tunnelCount);
85
+ const closeHandler = () => {
86
+ tunnel.destroy();
87
+ };
88
+ if (this.closed) {
89
+ closeHandler();
90
+ return;
91
+ }
92
+ this.once('close', closeHandler);
93
+ tunnel.once('close', () => {
94
+ this.removeListener('close', closeHandler);
95
+ });
96
+ });
97
+ this.tunnelCluster.on('dead', () => {
98
+ tunnelCount--;
99
+ log('tunnel dead [total: %d]', tunnelCount);
100
+ if (this.closed) {
101
+ return;
102
+ }
103
+ this.tunnelCluster.open();
104
+ });
105
+ this.tunnelCluster.on('request', (req) => {
106
+ this.emit('request', req);
107
+ });
108
+ for (let count = 0; count < info.max_conn; ++count) {
109
+ this.tunnelCluster.open();
110
+ }
111
+ }
112
+ open(cb) {
113
+ this._init((err, info) => {
114
+ if (err) {
115
+ cb(err);
116
+ return;
117
+ }
118
+ this.clientId = info.name;
119
+ this.url = info.url;
120
+ if (info.cached_url) {
121
+ this.cachedUrl = info.cached_url;
122
+ }
123
+ this._establish(info);
124
+ cb();
125
+ });
126
+ }
127
+ close() {
128
+ this.closed = true;
129
+ this.emit('close');
130
+ }
131
+ }
132
+ //# sourceMappingURL=Tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tunnel.js","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface TunnelClusterOptions {
3
+ name?: string;
4
+ url?: string;
5
+ cached_url?: string;
6
+ max_conn?: number;
7
+ remote_host?: string;
8
+ remote_ip?: string;
9
+ remote_port?: number;
10
+ local_port?: number;
11
+ local_host?: string;
12
+ local_https?: boolean;
13
+ local_cert?: string;
14
+ local_key?: string;
15
+ local_ca?: string;
16
+ allow_invalid_cert?: boolean;
17
+ }
18
+ export interface TunnelRequest {
19
+ method: string;
20
+ path: string;
21
+ }
22
+ export declare class TunnelCluster extends EventEmitter {
23
+ private opts;
24
+ constructor(opts?: TunnelClusterOptions);
25
+ open(): void;
26
+ }
27
+ //# sourceMappingURL=TunnelCluster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TunnelCluster.d.ts","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAUtC,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,aAAc,SAAQ,YAAY;IAC7C,OAAO,CAAC,IAAI,CAAuB;gBAEvB,IAAI,GAAE,oBAAyB;IAK3C,IAAI,IAAI,IAAI;CA4Hb"}
@@ -0,0 +1,101 @@
1
+ import { EventEmitter } from 'events';
2
+ import debug from 'debug';
3
+ import fs from 'fs';
4
+ import net from 'net';
5
+ import tls from 'tls';
6
+ import { HeaderHostTransformer } from './HeaderHostTransformer.js';
7
+ const log = debug('pipenet:client');
8
+ export class TunnelCluster extends EventEmitter {
9
+ opts;
10
+ constructor(opts = {}) {
11
+ super();
12
+ this.opts = opts;
13
+ }
14
+ open() {
15
+ const opt = this.opts;
16
+ const remoteHostOrIp = opt.remote_ip || opt.remote_host;
17
+ const remotePort = opt.remote_port;
18
+ const localHost = opt.local_host || 'localhost';
19
+ const localPort = opt.local_port;
20
+ const localProtocol = opt.local_https ? 'https' : 'http';
21
+ const allowInvalidCert = opt.allow_invalid_cert;
22
+ log('establishing tunnel %s://%s:%s <> %s:%s', localProtocol, localHost, localPort, remoteHostOrIp, remotePort);
23
+ const remote = net.connect({
24
+ host: remoteHostOrIp,
25
+ port: remotePort,
26
+ });
27
+ remote.setKeepAlive(true);
28
+ remote.on('error', (err) => {
29
+ log('got remote connection error', err.message);
30
+ if (err.code === 'ECONNREFUSED') {
31
+ this.emit('error', new Error(`connection refused: ${remoteHostOrIp}:${remotePort} (check your firewall settings)`));
32
+ }
33
+ remote.end();
34
+ });
35
+ const connLocal = () => {
36
+ if (remote.destroyed) {
37
+ log('remote destroyed');
38
+ this.emit('dead');
39
+ return;
40
+ }
41
+ log('connecting locally to %s://%s:%d', localProtocol, localHost, localPort);
42
+ remote.pause();
43
+ if (allowInvalidCert) {
44
+ log('allowing invalid certificates');
45
+ }
46
+ const getLocalCertOpts = () => allowInvalidCert
47
+ ? { rejectUnauthorized: false }
48
+ : {
49
+ cert: fs.readFileSync(opt.local_cert),
50
+ key: fs.readFileSync(opt.local_key),
51
+ ca: opt.local_ca ? [fs.readFileSync(opt.local_ca)] : undefined,
52
+ };
53
+ const local = opt.local_https
54
+ ? tls.connect({ host: localHost, port: localPort, ...getLocalCertOpts() })
55
+ : net.connect({ host: localHost, port: localPort });
56
+ const remoteClose = () => {
57
+ log('remote close');
58
+ this.emit('dead');
59
+ local.end();
60
+ };
61
+ remote.once('close', remoteClose);
62
+ local.once('error', (err) => {
63
+ log('local error %s', err.message);
64
+ local.end();
65
+ remote.removeListener('close', remoteClose);
66
+ if (err.code !== 'ECONNREFUSED' && err.code !== 'ECONNRESET') {
67
+ remote.end();
68
+ return;
69
+ }
70
+ setTimeout(connLocal, 1000);
71
+ });
72
+ local.once('connect', () => {
73
+ log('connected locally');
74
+ remote.resume();
75
+ let stream = remote;
76
+ if (opt.local_host) {
77
+ log('transform Host header to %s', opt.local_host);
78
+ stream = remote.pipe(new HeaderHostTransformer({ host: opt.local_host }));
79
+ }
80
+ stream.pipe(local).pipe(remote);
81
+ local.once('close', (hadError) => {
82
+ log('local connection closed [%s]', hadError);
83
+ });
84
+ });
85
+ };
86
+ remote.on('data', (data) => {
87
+ const match = data.toString().match(/^(\w+) (\S+)/);
88
+ if (match) {
89
+ this.emit('request', {
90
+ method: match[1],
91
+ path: match[2],
92
+ });
93
+ }
94
+ });
95
+ remote.once('connect', () => {
96
+ this.emit('open', remote);
97
+ connLocal();
98
+ });
99
+ }
100
+ }
101
+ //# sourceMappingURL=TunnelCluster.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TunnelCluster.js","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}