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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
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;AA6CpC,MAAM,UAAU,YAAY,CAAC,MAAqB,EAAE;IAClD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACnF,MAAM,OAAO,GAAG,KAAK,CAAC,gBAAgB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,IAAI,sBAAsB,CAAC;IAE1D,SAAS,uBAAuB,CAAC,QAAgB;QAC/C,OAAO,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAED,yDAAyD;IACzD,MAAM,YAAY,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAErE,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC;QAChC,GAAG,GAAG;QACN,YAAY;KACb,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IAElC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IACtB,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IAE5B,kBAAkB;IAClB,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,GAAG,CAAC,GAAG,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,iCAAiC,CAAC,CAAC;QAC3E,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,6BAA6B,CAAC,CAAC;QAEvE,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,GAAG,CAAC,IAAI,GAAG;YACT,GAAG,EAAE,OAAO,CAAC,WAAW,EAAE;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,GAAG;YACT,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;SACzC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACzB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;IAEjC,8DAA8D;IAC9D,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,EAAE;QACjC,iEAAiE;QACjE,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,iCAAiC;IACjC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,IAAY,EAAE,EAAE;QAC5C,OAAO,MAAM,GAAG,KAAK,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC;IAC1C,CAAC,CAAC;IAEF,0DAA0D;IAC1D,MAAM,aAAa,GAAG,CAAC,IAAsF,EAAE,EAAE;QAC/G,MAAM,QAAQ,GAA4B,EAAE,GAAG,IAAI,EAAE,CAAC;QACtD,yEAAyE;QACzE,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,GAAG,UAAU,CAAC;YAC3B,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC;QAC/B,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAE9B,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,MAAM,kBAAkB,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;QAC1D,IAAI,kBAAkB,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9C,GAAG,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YAC3C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAEzD,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO;QACT,CAAC;QAED,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,CAAC,sDAAsD,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACxE,MAAM,GAAG,GAAG,+FAA+F,CAAC;YAC5G,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;YACjB,GAAG,CAAC,IAAI,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9C,GAAG,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAEzD,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAkB,IAAI,CAAC,YAAY,EAAE,CAAC;IAClD,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;IAEnC,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAEnC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAChC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACnC,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,0BAA0B;QAC1B,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YAClB,GAAG,CAAC,SAAS,CAAC;gBACZ,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,KAAK;gBAC3B,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG;gBACpB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,aAAa;gBACvC,QAAQ,EAAE,QAAQ;aACnB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACnC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -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":"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"}
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.3.0",
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": "^5.82.0",
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: { destroy: () => void; once: (event: string, handler: () => void) => void }) => {
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
  }
@@ -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
 
@@ -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?: string): Promise<NewClientInfo> {
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
  }
@@ -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
  });