pipenet 1.3.0 → 1.4.1
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.
- package/README.md +76 -4
- package/dist/Tunnel.d.ts.map +1 -1
- package/dist/Tunnel.js +12 -1
- package/dist/Tunnel.js.map +1 -1
- package/dist/TunnelCluster.js +2 -2
- package/dist/TunnelCluster.js.map +1 -1
- package/dist/pipenet.spec.js +17 -0
- package/dist/pipenet.spec.js.map +1 -1
- package/dist/server/ClientManager.d.ts +11 -1
- package/dist/server/ClientManager.d.ts.map +1 -1
- package/dist/server/ClientManager.js +18 -1
- package/dist/server/ClientManager.js.map +1 -1
- package/dist/server/ClientManager.spec.js +8 -8
- package/dist/server/ClientManager.spec.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/server.d.ts +27 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +29 -7
- package/dist/server/server.js.map +1 -1
- package/dist/server/server.spec.js +104 -1
- package/dist/server/server.spec.js.map +1 -1
- package/package.json +2 -2
- package/src/Tunnel.ts +16 -2
- package/src/TunnelCluster.ts +2 -2
- package/src/pipenet.spec.ts +21 -0
- package/src/server/ClientManager.spec.ts +8 -8
- package/src/server/ClientManager.ts +33 -1
- package/src/server/index.ts +2 -2
- package/src/server/server.spec.ts +133 -1
- package/src/server/server.ts +64 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACzC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,YAAY,CAAC;AAChC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,MAAM,GAAG,GAAG,KAAK,CAAC,gBAAgB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import net from 'net';
|
|
2
2
|
import request from 'supertest';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import { WebSocket, WebSocketServer } from 'ws';
|
|
5
5
|
import { createServer } from './server.js';
|
|
6
6
|
describe('Server', () => {
|
|
@@ -109,5 +109,108 @@ describe('Server', () => {
|
|
|
109
109
|
expect(res.statusCode).toBe(204);
|
|
110
110
|
expect(res.headers['access-control-allow-origin']).toBe('*');
|
|
111
111
|
});
|
|
112
|
+
describe('hooks', () => {
|
|
113
|
+
it('should call onTunnelCreated when a tunnel is created', async () => {
|
|
114
|
+
const onTunnelCreated = vi.fn();
|
|
115
|
+
const server = createServer({ onTunnelCreated });
|
|
116
|
+
await new Promise(resolve => server.listen(resolve));
|
|
117
|
+
await request(server).get('/test-tunnel');
|
|
118
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
119
|
+
expect(onTunnelCreated).toHaveBeenCalledWith(expect.objectContaining({
|
|
120
|
+
domain: expect.any(String),
|
|
121
|
+
id: 'test-tunnel',
|
|
122
|
+
url: expect.stringContaining('test-tunnel'),
|
|
123
|
+
}));
|
|
124
|
+
await new Promise(resolve => server.close(() => resolve()));
|
|
125
|
+
});
|
|
126
|
+
it('should include domain in tunnel hooks', async () => {
|
|
127
|
+
const onTunnelCreated = vi.fn();
|
|
128
|
+
const server = createServer({
|
|
129
|
+
domains: ['tunnel.example.com'],
|
|
130
|
+
onTunnelCreated,
|
|
131
|
+
});
|
|
132
|
+
await new Promise(resolve => server.listen(resolve));
|
|
133
|
+
await request(server)
|
|
134
|
+
.get('/domain-test')
|
|
135
|
+
.set('Host', 'tunnel.example.com');
|
|
136
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
137
|
+
expect(onTunnelCreated).toHaveBeenCalledWith({
|
|
138
|
+
domain: 'tunnel.example.com',
|
|
139
|
+
id: 'domain-test',
|
|
140
|
+
url: 'http://domain-test.tunnel.example.com',
|
|
141
|
+
});
|
|
142
|
+
await new Promise(resolve => server.close(() => resolve()));
|
|
143
|
+
});
|
|
144
|
+
it('should call onTunnelClosed when a tunnel is closed', async () => {
|
|
145
|
+
const onTunnelCreated = vi.fn();
|
|
146
|
+
const onTunnelClosed = vi.fn();
|
|
147
|
+
const server = createServer({ onTunnelClosed, onTunnelCreated });
|
|
148
|
+
await new Promise(resolve => server.listen(resolve));
|
|
149
|
+
const res = await request(server).get('/close-test');
|
|
150
|
+
const localTunnelPort = res.body.port;
|
|
151
|
+
// Connect a socket to activate the tunnel
|
|
152
|
+
const socket = net.createConnection({ port: localTunnelPort });
|
|
153
|
+
await new Promise(resolve => socket.once('connect', resolve));
|
|
154
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
155
|
+
expect(onTunnelClosed).not.toHaveBeenCalled();
|
|
156
|
+
// Close the socket to trigger tunnel close
|
|
157
|
+
socket.destroy();
|
|
158
|
+
// Wait for the close event to propagate (Client has a 1s grace timeout after offline)
|
|
159
|
+
await new Promise(resolve => setTimeout(resolve, 1200));
|
|
160
|
+
expect(onTunnelClosed).toHaveBeenCalledTimes(1);
|
|
161
|
+
expect(onTunnelClosed).toHaveBeenCalledWith(expect.objectContaining({
|
|
162
|
+
domain: expect.any(String),
|
|
163
|
+
id: 'close-test',
|
|
164
|
+
url: expect.stringContaining('close-test'),
|
|
165
|
+
}));
|
|
166
|
+
await new Promise(resolve => server.close(() => resolve()));
|
|
167
|
+
}, 5000);
|
|
168
|
+
it('should call onRequest when a request is proxied', async () => {
|
|
169
|
+
const onRequest = vi.fn();
|
|
170
|
+
const server = createServer({
|
|
171
|
+
domains: ['example.com'],
|
|
172
|
+
onRequest,
|
|
173
|
+
});
|
|
174
|
+
await new Promise(resolve => server.listen(resolve));
|
|
175
|
+
// Create a tunnel
|
|
176
|
+
const res = await request(server).get('/request-test');
|
|
177
|
+
const localTunnelPort = res.body.port;
|
|
178
|
+
// Create a simple echo server
|
|
179
|
+
const echoServer = net.createServer((socket) => {
|
|
180
|
+
socket.on('data', () => {
|
|
181
|
+
const response = 'HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK';
|
|
182
|
+
socket.write(response);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
await new Promise(resolve => echoServer.listen(0, resolve));
|
|
186
|
+
const echoPort = echoServer.address().port;
|
|
187
|
+
// Connect tunnel socket to echo server
|
|
188
|
+
const ltSocket = net.createConnection({ port: localTunnelPort });
|
|
189
|
+
const echoSocket = net.createConnection({ port: echoPort });
|
|
190
|
+
await Promise.all([
|
|
191
|
+
new Promise(resolve => ltSocket.once('connect', resolve)),
|
|
192
|
+
new Promise(resolve => echoSocket.once('connect', resolve)),
|
|
193
|
+
]);
|
|
194
|
+
ltSocket.pipe(echoSocket).pipe(ltSocket);
|
|
195
|
+
// Make a request through the tunnel
|
|
196
|
+
await request(server)
|
|
197
|
+
.get('/some/path')
|
|
198
|
+
.set('Host', 'request-test.example.com');
|
|
199
|
+
expect(onRequest).toHaveBeenCalledTimes(1);
|
|
200
|
+
expect(onRequest).toHaveBeenCalledWith({
|
|
201
|
+
headers: expect.objectContaining({
|
|
202
|
+
host: 'request-test.example.com',
|
|
203
|
+
}),
|
|
204
|
+
method: 'GET',
|
|
205
|
+
path: '/some/path',
|
|
206
|
+
remoteAddress: expect.any(String),
|
|
207
|
+
tunnelId: 'request-test',
|
|
208
|
+
});
|
|
209
|
+
ltSocket.destroy();
|
|
210
|
+
echoSocket.destroy();
|
|
211
|
+
echoServer.close();
|
|
212
|
+
await new Promise(resolve => server.close(() => resolve()));
|
|
213
|
+
});
|
|
214
|
+
});
|
|
112
215
|
});
|
|
113
216
|
//# sourceMappingURL=server.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.spec.js","sourceRoot":"","sources":["../../src/server/server.spec.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"server.spec.js","sourceRoot":"","sources":["../../src/server/server.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipenet",
|
|
3
3
|
"description": "Expose your local server to the public internet instantly",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/pipenet.js",
|
|
7
7
|
"types": "./dist/pipenet.d.ts",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"eslint-config-prettier": "^10.1.8",
|
|
71
71
|
"eslint-plugin-perfectionist": "^5.3.1",
|
|
72
72
|
"jiti": "^2.6.1",
|
|
73
|
-
"knip": "^
|
|
73
|
+
"knip": "^6.13.1",
|
|
74
74
|
"semantic-release": "^25.0.2",
|
|
75
75
|
"supertest": "^7.2.2",
|
|
76
76
|
"typescript": "^5.9.3",
|
package/src/Tunnel.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import debug from 'debug';
|
|
3
3
|
import { EventEmitter } from 'events';
|
|
4
|
+
import net from 'net';
|
|
4
5
|
|
|
5
6
|
import { TunnelCluster, TunnelClusterOptions } from './TunnelCluster.js';
|
|
6
7
|
|
|
@@ -104,8 +105,9 @@ export class Tunnel extends EventEmitter {
|
|
|
104
105
|
});
|
|
105
106
|
|
|
106
107
|
let tunnelCount = 0;
|
|
108
|
+
const tunnelHandlers = new Map<net.Socket, () => void>();
|
|
107
109
|
|
|
108
|
-
this.tunnelCluster.on('open', (tunnel:
|
|
110
|
+
this.tunnelCluster.on('open', (tunnel: net.Socket) => {
|
|
109
111
|
tunnelCount++;
|
|
110
112
|
log('tunnel open [total: %d]', tunnelCount);
|
|
111
113
|
|
|
@@ -118,15 +120,27 @@ export class Tunnel extends EventEmitter {
|
|
|
118
120
|
return;
|
|
119
121
|
}
|
|
120
122
|
|
|
123
|
+
tunnelHandlers.set(tunnel, closeHandler);
|
|
121
124
|
this.once('close', closeHandler);
|
|
122
125
|
tunnel.once('close', () => {
|
|
126
|
+
tunnelHandlers.delete(tunnel);
|
|
123
127
|
this.removeListener('close', closeHandler);
|
|
124
128
|
});
|
|
125
129
|
});
|
|
126
130
|
|
|
127
|
-
this.tunnelCluster.on('dead', () => {
|
|
131
|
+
this.tunnelCluster.on('dead', (deadSocket?: net.Socket) => {
|
|
128
132
|
tunnelCount--;
|
|
129
133
|
log('tunnel dead [total: %d]', tunnelCount);
|
|
134
|
+
|
|
135
|
+
// Eagerly remove the close handler for the dead tunnel.
|
|
136
|
+
// Without this, the handler lingers until the socket's async
|
|
137
|
+
// 'close' event fires, causing listener accumulation.
|
|
138
|
+
if (deadSocket && tunnelHandlers.has(deadSocket)) {
|
|
139
|
+
const handler = tunnelHandlers.get(deadSocket)!;
|
|
140
|
+
tunnelHandlers.delete(deadSocket);
|
|
141
|
+
this.removeListener('close', handler);
|
|
142
|
+
}
|
|
143
|
+
|
|
130
144
|
if (this.closed) {
|
|
131
145
|
return;
|
|
132
146
|
}
|
package/src/TunnelCluster.ts
CHANGED
|
@@ -83,7 +83,7 @@ export class TunnelCluster extends EventEmitter {
|
|
|
83
83
|
const connLocal = (): void => {
|
|
84
84
|
if (remote.destroyed) {
|
|
85
85
|
log('remote destroyed');
|
|
86
|
-
this.emit('dead');
|
|
86
|
+
this.emit('dead', remote);
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -109,7 +109,7 @@ export class TunnelCluster extends EventEmitter {
|
|
|
109
109
|
|
|
110
110
|
const remoteClose = (): void => {
|
|
111
111
|
log('remote close');
|
|
112
|
-
this.emit('dead');
|
|
112
|
+
this.emit('dead', remote);
|
|
113
113
|
local.end();
|
|
114
114
|
};
|
|
115
115
|
|
package/src/pipenet.spec.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AddressInfo } from 'net';
|
|
2
2
|
|
|
3
3
|
import axios from 'axios';
|
|
4
|
+
import { EventEmitter } from 'events';
|
|
4
5
|
import http from 'http';
|
|
5
6
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
6
7
|
|
|
@@ -96,4 +97,24 @@ describe('custom headers', () => {
|
|
|
96
97
|
});
|
|
97
98
|
});
|
|
98
99
|
|
|
100
|
+
it('does not leak close listeners across tunnel reconnections', async () => {
|
|
101
|
+
const tunnel = await pipenet(fakePort, { host });
|
|
102
|
+
const cluster = tunnel.tunnelCluster!;
|
|
103
|
+
|
|
104
|
+
const before = tunnel.listenerCount('close');
|
|
105
|
+
|
|
106
|
+
// Force rapid reconnection cycles by emitting open→dead on the cluster.
|
|
107
|
+
for (let i = 0; i < 20; i++) {
|
|
108
|
+
const fakeSocket = new EventEmitter() as { destroy: () => void } & EventEmitter;
|
|
109
|
+
fakeSocket.destroy = () => {};
|
|
110
|
+
cluster.emit('open', fakeSocket);
|
|
111
|
+
cluster.emit('dead', fakeSocket);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Without the fix, 20 close handlers would accumulate.
|
|
115
|
+
// With eager cleanup, count should not grow.
|
|
116
|
+
expect(tunnel.listenerCount('close')).toBe(before);
|
|
117
|
+
tunnel.close();
|
|
118
|
+
});
|
|
119
|
+
|
|
99
120
|
});
|
|
@@ -11,22 +11,22 @@ describe('ClientManager', () => {
|
|
|
11
11
|
|
|
12
12
|
it('should create a new client with random id', async () => {
|
|
13
13
|
const manager = new ClientManager();
|
|
14
|
-
const client = await manager.newClient();
|
|
14
|
+
const client = await manager.newClient(undefined, 'http://test.example.com', 'example.com');
|
|
15
15
|
expect(manager.hasClient(client.id)).toBe(true);
|
|
16
16
|
manager.removeClient(client.id);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
it('should create a new client with id', async () => {
|
|
20
20
|
const manager = new ClientManager();
|
|
21
|
-
await manager.newClient('foobar');
|
|
21
|
+
await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
|
|
22
22
|
expect(manager.hasClient('foobar')).toBe(true);
|
|
23
23
|
manager.removeClient('foobar');
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
it('should create a new client with random id if previous exists', async () => {
|
|
27
27
|
const manager = new ClientManager();
|
|
28
|
-
const clientA = await manager.newClient('foobar');
|
|
29
|
-
const clientB = await manager.newClient('foobar');
|
|
28
|
+
const clientA = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
|
|
29
|
+
const clientB = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
|
|
30
30
|
expect(clientA.id).toBe('foobar');
|
|
31
31
|
expect(manager.hasClient(clientB.id)).toBe(true);
|
|
32
32
|
expect(clientB.id).not.toBe(clientA.id);
|
|
@@ -36,7 +36,7 @@ describe('ClientManager', () => {
|
|
|
36
36
|
|
|
37
37
|
it('should remove client once it goes offline', async () => {
|
|
38
38
|
const manager = new ClientManager();
|
|
39
|
-
const client = await manager.newClient('foobar');
|
|
39
|
+
const client = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
|
|
40
40
|
|
|
41
41
|
const socket = await new Promise<net.Socket>((resolve) => {
|
|
42
42
|
const netClient = net.createConnection({ port: client.port }, () => {
|
|
@@ -57,8 +57,8 @@ describe('ClientManager', () => {
|
|
|
57
57
|
|
|
58
58
|
it('should remove correct client once it goes offline', async () => {
|
|
59
59
|
const manager = new ClientManager();
|
|
60
|
-
const clientFoo = await manager.newClient('foo');
|
|
61
|
-
await manager.newClient('bar');
|
|
60
|
+
const clientFoo = await manager.newClient('foo', 'http://foo.example.com', 'example.com');
|
|
61
|
+
await manager.newClient('bar', 'http://bar.example.com', 'example.com');
|
|
62
62
|
|
|
63
63
|
const socket = await new Promise<net.Socket>((resolve) => {
|
|
64
64
|
const netClient = net.createConnection({ port: clientFoo.port }, () => {
|
|
@@ -80,7 +80,7 @@ describe('ClientManager', () => {
|
|
|
80
80
|
|
|
81
81
|
it('should remove clients if they do not connect within 5 seconds', async () => {
|
|
82
82
|
const manager = new ClientManager();
|
|
83
|
-
await manager.newClient('foo');
|
|
83
|
+
await manager.newClient('foo', 'http://foo.example.com', 'example.com');
|
|
84
84
|
expect(manager.hasClient('foo')).toBe(true);
|
|
85
85
|
|
|
86
86
|
// wait past grace period (1s)
|
|
@@ -8,24 +8,36 @@ import { TunnelAgent } from './TunnelAgent.js';
|
|
|
8
8
|
|
|
9
9
|
export interface ClientManagerOptions {
|
|
10
10
|
maxTcpSockets?: number;
|
|
11
|
+
onTunnelClosed?: (tunnel: TunnelInfo) => void;
|
|
12
|
+
onTunnelCreated?: (tunnel: TunnelInfo) => void;
|
|
11
13
|
tunnelServer?: TunnelServer;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface NewClientInfo {
|
|
17
|
+
domain: string;
|
|
15
18
|
id: string;
|
|
16
19
|
maxConnCount?: number;
|
|
17
20
|
port: number;
|
|
21
|
+
url: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TunnelInfo {
|
|
25
|
+
domain: string;
|
|
26
|
+
id: string;
|
|
27
|
+
url: string;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
export class ClientManager {
|
|
21
31
|
public stats: { tunnels: number };
|
|
22
32
|
private clients: Map<string, Client>;
|
|
33
|
+
private clientTunnelInfo: Map<string, { domain: string; url: string }>;
|
|
23
34
|
private log: debug.Debugger;
|
|
24
35
|
private opt: ClientManagerOptions;
|
|
25
36
|
|
|
26
37
|
constructor(opt: ClientManagerOptions = {}) {
|
|
27
38
|
this.opt = opt;
|
|
28
39
|
this.clients = new Map();
|
|
40
|
+
this.clientTunnelInfo = new Map();
|
|
29
41
|
this.stats = { tunnels: 0 };
|
|
30
42
|
this.log = debug('lt:ClientManager');
|
|
31
43
|
}
|
|
@@ -38,7 +50,7 @@ export class ClientManager {
|
|
|
38
50
|
return this.clients.has(id);
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
async newClient(requestedId
|
|
53
|
+
async newClient(requestedId: string | undefined, url: string, domain: string): Promise<NewClientInfo> {
|
|
42
54
|
let id: string;
|
|
43
55
|
if (requestedId && !this.clients.has(requestedId)) {
|
|
44
56
|
id = requestedId;
|
|
@@ -56,6 +68,7 @@ export class ClientManager {
|
|
|
56
68
|
const client = new Client({ agent, id });
|
|
57
69
|
|
|
58
70
|
this.clients.set(id, client);
|
|
71
|
+
this.clientTunnelInfo.set(id, { domain, url });
|
|
59
72
|
|
|
60
73
|
client.once('close', () => {
|
|
61
74
|
this.removeClient(id);
|
|
@@ -64,10 +77,18 @@ export class ClientManager {
|
|
|
64
77
|
try {
|
|
65
78
|
const info = await agent.listen();
|
|
66
79
|
++this.stats.tunnels;
|
|
80
|
+
|
|
81
|
+
// Call the onTunnelCreated hook
|
|
82
|
+
if (this.opt.onTunnelCreated) {
|
|
83
|
+
this.opt.onTunnelCreated({ domain, id, url });
|
|
84
|
+
}
|
|
85
|
+
|
|
67
86
|
return {
|
|
87
|
+
domain,
|
|
68
88
|
id: id,
|
|
69
89
|
maxConnCount: maxSockets,
|
|
70
90
|
port: info.port,
|
|
91
|
+
url,
|
|
71
92
|
};
|
|
72
93
|
} catch (err) {
|
|
73
94
|
this.removeClient(id);
|
|
@@ -79,8 +100,19 @@ export class ClientManager {
|
|
|
79
100
|
this.log('removing client: %s', id);
|
|
80
101
|
const client = this.clients.get(id);
|
|
81
102
|
if (!client) return;
|
|
103
|
+
|
|
104
|
+
const tunnelInfo = this.clientTunnelInfo.get(id);
|
|
105
|
+
const domain = tunnelInfo?.domain || '';
|
|
106
|
+
const url = tunnelInfo?.url || '';
|
|
107
|
+
|
|
82
108
|
--this.stats.tunnels;
|
|
83
109
|
this.clients.delete(id);
|
|
110
|
+
this.clientTunnelInfo.delete(id);
|
|
84
111
|
client.close();
|
|
112
|
+
|
|
113
|
+
// Call the onTunnelClosed hook
|
|
114
|
+
if (this.opt.onTunnelClosed) {
|
|
115
|
+
this.opt.onTunnelClosed({ domain, id, url });
|
|
116
|
+
}
|
|
85
117
|
}
|
|
86
118
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Client, type ClientOptions } from './Client.js';
|
|
2
|
-
export { ClientManager, type ClientManagerOptions, type NewClientInfo } from './ClientManager.js';
|
|
3
|
-
export { createServer, type PipenetServer, type ServerOptions } from './server.js';
|
|
2
|
+
export { ClientManager, type ClientManagerOptions, type NewClientInfo, type TunnelInfo } from './ClientManager.js';
|
|
3
|
+
export { createServer, type PipenetServer, type RequestInfo, type ServerHooks, type ServerOptions } from './server.js';
|
|
4
4
|
export { TunnelAgent, type TunnelAgentListenInfo, type TunnelAgentOptions, type TunnelAgentStats } from './TunnelAgent.js';
|
|
5
5
|
export { type SocketHandler, TunnelServer } from './TunnelServer.js';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import net from 'net';
|
|
2
2
|
import request from 'supertest';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import { WebSocket, WebSocketServer } from 'ws';
|
|
5
5
|
|
|
6
|
+
import type { RequestInfo, TunnelInfo } from './server.js';
|
|
7
|
+
|
|
6
8
|
import { createServer } from './server.js';
|
|
7
9
|
|
|
8
10
|
describe('Server', () => {
|
|
@@ -136,4 +138,134 @@ describe('Server', () => {
|
|
|
136
138
|
expect(res.statusCode).toBe(204);
|
|
137
139
|
expect(res.headers['access-control-allow-origin']).toBe('*');
|
|
138
140
|
});
|
|
141
|
+
|
|
142
|
+
describe('hooks', () => {
|
|
143
|
+
it('should call onTunnelCreated when a tunnel is created', async () => {
|
|
144
|
+
const onTunnelCreated = vi.fn<(tunnel: TunnelInfo) => void>();
|
|
145
|
+
const server = createServer({ onTunnelCreated });
|
|
146
|
+
await new Promise<void>(resolve => server.listen(resolve));
|
|
147
|
+
|
|
148
|
+
await request(server).get('/test-tunnel');
|
|
149
|
+
|
|
150
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
151
|
+
expect(onTunnelCreated).toHaveBeenCalledWith(
|
|
152
|
+
expect.objectContaining({
|
|
153
|
+
domain: expect.any(String),
|
|
154
|
+
id: 'test-tunnel',
|
|
155
|
+
url: expect.stringContaining('test-tunnel'),
|
|
156
|
+
})
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
await new Promise<void>(resolve => server.close(() => resolve()));
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should include domain in tunnel hooks', async () => {
|
|
163
|
+
const onTunnelCreated = vi.fn<(tunnel: TunnelInfo) => void>();
|
|
164
|
+
const server = createServer({
|
|
165
|
+
domains: ['tunnel.example.com'],
|
|
166
|
+
onTunnelCreated,
|
|
167
|
+
});
|
|
168
|
+
await new Promise<void>(resolve => server.listen(resolve));
|
|
169
|
+
|
|
170
|
+
await request(server)
|
|
171
|
+
.get('/domain-test')
|
|
172
|
+
.set('Host', 'tunnel.example.com');
|
|
173
|
+
|
|
174
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
175
|
+
expect(onTunnelCreated).toHaveBeenCalledWith({
|
|
176
|
+
domain: 'tunnel.example.com',
|
|
177
|
+
id: 'domain-test',
|
|
178
|
+
url: 'http://domain-test.tunnel.example.com',
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
await new Promise<void>(resolve => server.close(() => resolve()));
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it('should call onTunnelClosed when a tunnel is closed', async () => {
|
|
185
|
+
const onTunnelCreated = vi.fn<(tunnel: TunnelInfo) => void>();
|
|
186
|
+
const onTunnelClosed = vi.fn<(tunnel: TunnelInfo) => void>();
|
|
187
|
+
const server = createServer({ onTunnelClosed, onTunnelCreated });
|
|
188
|
+
await new Promise<void>(resolve => server.listen(resolve));
|
|
189
|
+
|
|
190
|
+
const res = await request(server).get('/close-test');
|
|
191
|
+
const localTunnelPort = res.body.port;
|
|
192
|
+
|
|
193
|
+
// Connect a socket to activate the tunnel
|
|
194
|
+
const socket = net.createConnection({ port: localTunnelPort });
|
|
195
|
+
await new Promise<void>(resolve => socket.once('connect', resolve));
|
|
196
|
+
|
|
197
|
+
expect(onTunnelCreated).toHaveBeenCalledTimes(1);
|
|
198
|
+
expect(onTunnelClosed).not.toHaveBeenCalled();
|
|
199
|
+
|
|
200
|
+
// Close the socket to trigger tunnel close
|
|
201
|
+
socket.destroy();
|
|
202
|
+
|
|
203
|
+
// Wait for the close event to propagate (Client has a 1s grace timeout after offline)
|
|
204
|
+
await new Promise(resolve => setTimeout(resolve, 1200));
|
|
205
|
+
|
|
206
|
+
expect(onTunnelClosed).toHaveBeenCalledTimes(1);
|
|
207
|
+
expect(onTunnelClosed).toHaveBeenCalledWith(
|
|
208
|
+
expect.objectContaining({
|
|
209
|
+
domain: expect.any(String),
|
|
210
|
+
id: 'close-test',
|
|
211
|
+
url: expect.stringContaining('close-test'),
|
|
212
|
+
})
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
await new Promise<void>(resolve => server.close(() => resolve()));
|
|
216
|
+
}, 5000);
|
|
217
|
+
|
|
218
|
+
it('should call onRequest when a request is proxied', async () => {
|
|
219
|
+
const onRequest = vi.fn<(request: RequestInfo) => void>();
|
|
220
|
+
const server = createServer({
|
|
221
|
+
domains: ['example.com'],
|
|
222
|
+
onRequest,
|
|
223
|
+
});
|
|
224
|
+
await new Promise<void>(resolve => server.listen(resolve));
|
|
225
|
+
|
|
226
|
+
// Create a tunnel
|
|
227
|
+
const res = await request(server).get('/request-test');
|
|
228
|
+
const localTunnelPort = res.body.port;
|
|
229
|
+
|
|
230
|
+
// Create a simple echo server
|
|
231
|
+
const echoServer = net.createServer((socket) => {
|
|
232
|
+
socket.on('data', () => {
|
|
233
|
+
const response = 'HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK';
|
|
234
|
+
socket.write(response);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
await new Promise<void>(resolve => echoServer.listen(0, resolve));
|
|
238
|
+
const echoPort = (echoServer.address() as net.AddressInfo).port;
|
|
239
|
+
|
|
240
|
+
// Connect tunnel socket to echo server
|
|
241
|
+
const ltSocket = net.createConnection({ port: localTunnelPort });
|
|
242
|
+
const echoSocket = net.createConnection({ port: echoPort });
|
|
243
|
+
await Promise.all([
|
|
244
|
+
new Promise<void>(resolve => ltSocket.once('connect', resolve)),
|
|
245
|
+
new Promise<void>(resolve => echoSocket.once('connect', resolve)),
|
|
246
|
+
]);
|
|
247
|
+
ltSocket.pipe(echoSocket).pipe(ltSocket);
|
|
248
|
+
|
|
249
|
+
// Make a request through the tunnel
|
|
250
|
+
await request(server)
|
|
251
|
+
.get('/some/path')
|
|
252
|
+
.set('Host', 'request-test.example.com');
|
|
253
|
+
|
|
254
|
+
expect(onRequest).toHaveBeenCalledTimes(1);
|
|
255
|
+
expect(onRequest).toHaveBeenCalledWith({
|
|
256
|
+
headers: expect.objectContaining({
|
|
257
|
+
host: 'request-test.example.com',
|
|
258
|
+
}),
|
|
259
|
+
method: 'GET',
|
|
260
|
+
path: '/some/path',
|
|
261
|
+
remoteAddress: expect.any(String),
|
|
262
|
+
tunnelId: 'request-test',
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
ltSocket.destroy();
|
|
266
|
+
echoSocket.destroy();
|
|
267
|
+
echoServer.close();
|
|
268
|
+
await new Promise<void>(resolve => server.close(() => resolve()));
|
|
269
|
+
});
|
|
270
|
+
});
|
|
139
271
|
});
|