pipenet 1.3.0 → 1.4.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.
package/README.md CHANGED
@@ -6,8 +6,6 @@ Expose your local server to the public internet instantly
6
6
 
7
7
  ```bash
8
8
  npm install pipenet
9
- # or
10
- pnpm add pipenet
11
9
  ```
12
10
 
13
11
  ## CLI Usage
@@ -104,11 +102,22 @@ npx pipenet server --port 3000 --tunnel-port 3001 --domain tunnel.example.com
104
102
  import { createServer } from 'pipenet/server';
105
103
 
106
104
  const server = createServer({
107
- domains: ['tunnel.example.com'], // Optional: custom domain(s)
105
+ domains: ['tunnel.example.com'], // Optional: custom domain(s)
108
106
  secure: false, // Optional: require HTTPS
109
107
  landing: 'https://pipenet.dev', // Optional: landing page URL
110
108
  maxTcpSockets: 10, // Optional: max sockets per client
111
109
  tunnelPort: 3001, // Optional: shared tunnel port for cloud deployments
110
+
111
+ // Lifecycle hooks for tracking tunnels and requests
112
+ onTunnelCreated: (tunnel) => {
113
+ console.log(`Tunnel created: ${tunnel.id} at ${tunnel.url}`);
114
+ },
115
+ onTunnelClosed: (tunnel) => {
116
+ console.log(`Tunnel closed: ${tunnel.id}`);
117
+ },
118
+ onRequest: (request) => {
119
+ console.log(`Request: ${request.method} ${request.path} via ${request.tunnelId}`);
120
+ },
112
121
  });
113
122
 
114
123
  // Start tunnel server if using shared tunnel port
@@ -129,6 +138,18 @@ server.listen(3000, () => {
129
138
  - `maxTcpSockets` (number) Maximum number of TCP sockets per client (default: 10)
130
139
  - `tunnelPort` (number) Shared tunnel port for cloud deployments (enables single-port mode)
131
140
 
141
+ ### Server Hooks
142
+
143
+ The server supports lifecycle hooks for tracking tunnels and requests:
144
+
145
+ - `onTunnelCreated(tunnel)` - Called when a new tunnel is created. Receives `{ id, url, domain }`.
146
+ - `onTunnelClosed(tunnel)` - Called when a tunnel is closed. Receives `{ id, url, domain }`.
147
+ - `onRequest(request)` - Called when a request is proxied through a tunnel. Receives `{ method, path, tunnelId, headers, remoteAddress }`.
148
+
149
+ The `domain` field identifies which configured domain was used when the tunnel was created, which is useful when running a server with multiple domains.
150
+
151
+ The `onRequest` hook provides access to request headers and the client's remote IP address, useful for logging, rate limiting, or authentication.
152
+
132
153
  ### Server API Endpoints
133
154
 
134
155
  - `GET /api/status` - Server status and tunnel count
@@ -172,6 +193,25 @@ pipenet was developed by [glama.ai](https://glama.ai) to enable local [Model Con
172
193
 
173
194
  This capability is now integrated into [mcp-proxy](https://github.com/punkpeye/mcp-proxy).
174
195
 
196
+ ## pipenet vs localtunnel
197
+
198
+ pipenet is a modernized fork of [localtunnel](https://github.com/localtunnel/localtunnel) with several improvements:
199
+
200
+ | Feature | pipenet | localtunnel |
201
+ | ------- | ------- | ----------- |
202
+ | Cloud deployment support | ✅ Single-port mode via `--tunnel-port` | ❌ Requires random ports |
203
+ | Multiple domains | ✅ `--domain` can be specified multiple times | ❌ Single domain only |
204
+ | TypeScript | ✅ Written in TypeScript with full type definitions | ❌ JavaScript only |
205
+ | ESM support | ✅ Native ES modules | ❌ CommonJS only |
206
+ | Active maintenance | ✅ Actively maintained | ⚠️ Limited maintenance |
207
+ | WebSocket support | ✅ Full WebSocket proxying | ✅ Full WebSocket proxying |
208
+
209
+ ### Key Differences
210
+
211
+ **Cloud Deployment Support**: localtunnel creates a random TCP port for each tunnel client, which doesn't work in containerized environments like Docker, fly.io, or Kubernetes where only specific ports are exposed. pipenet solves this with the `--tunnel-port` option, enabling all clients to connect through a single shared port.
212
+
213
+ **Modern JavaScript**: pipenet uses ES modules and is written in TypeScript, providing better IDE support, type safety, and compatibility with modern JavaScript tooling.
214
+
175
215
  ## Acknowledgments
176
216
 
177
217
  pipenet is based on [localtunnel](https://github.com/localtunnel/localtunnel).
@@ -2,24 +2,34 @@ import type { TunnelServer } from './TunnelServer.js';
2
2
  import { Client } from './Client.js';
3
3
  export interface ClientManagerOptions {
4
4
  maxTcpSockets?: number;
5
+ onTunnelClosed?: (tunnel: TunnelInfo) => void;
6
+ onTunnelCreated?: (tunnel: TunnelInfo) => void;
5
7
  tunnelServer?: TunnelServer;
6
8
  }
7
9
  export interface NewClientInfo {
10
+ domain: string;
8
11
  id: string;
9
12
  maxConnCount?: number;
10
13
  port: number;
14
+ url: string;
15
+ }
16
+ export interface TunnelInfo {
17
+ domain: string;
18
+ id: string;
19
+ url: string;
11
20
  }
12
21
  export declare class ClientManager {
13
22
  stats: {
14
23
  tunnels: number;
15
24
  };
16
25
  private clients;
26
+ private clientTunnelInfo;
17
27
  private log;
18
28
  private opt;
19
29
  constructor(opt?: ClientManagerOptions);
20
30
  getClient(id: string): Client | undefined;
21
31
  hasClient(id: string): boolean;
22
- newClient(requestedId?: string): Promise<NewClientInfo>;
32
+ newClient(requestedId: string | undefined, url: string, domain: string): Promise<NewClientInfo>;
23
33
  removeClient(id: string): void;
24
34
  }
25
35
  //# sourceMappingURL=ClientManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClientManager.d.ts","sourceRoot":"","sources":["../../src/server/ClientManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,aAAa;IACjB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,GAAG,CAAuB;gBAEtB,GAAG,GAAE,oBAAyB;IAO1C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIzC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqC7D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAQ/B"}
1
+ {"version":3,"file":"ClientManager.d.ts","sourceRoot":"","sources":["../../src/server/ClientManager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,aAAa;IACjB,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,gBAAgB,CAA+C;IACvE,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,GAAG,CAAuB;gBAEtB,GAAG,GAAE,oBAAyB;IAQ1C,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIzC,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA8CrG,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAmB/B"}
@@ -5,11 +5,13 @@ import { TunnelAgent } from './TunnelAgent.js';
5
5
  export class ClientManager {
6
6
  stats;
7
7
  clients;
8
+ clientTunnelInfo;
8
9
  log;
9
10
  opt;
10
11
  constructor(opt = {}) {
11
12
  this.opt = opt;
12
13
  this.clients = new Map();
14
+ this.clientTunnelInfo = new Map();
13
15
  this.stats = { tunnels: 0 };
14
16
  this.log = debug('lt:ClientManager');
15
17
  }
@@ -19,7 +21,7 @@ export class ClientManager {
19
21
  hasClient(id) {
20
22
  return this.clients.has(id);
21
23
  }
22
- async newClient(requestedId) {
24
+ async newClient(requestedId, url, domain) {
23
25
  let id;
24
26
  if (requestedId && !this.clients.has(requestedId)) {
25
27
  id = requestedId;
@@ -35,16 +37,23 @@ export class ClientManager {
35
37
  });
36
38
  const client = new Client({ agent, id });
37
39
  this.clients.set(id, client);
40
+ this.clientTunnelInfo.set(id, { domain, url });
38
41
  client.once('close', () => {
39
42
  this.removeClient(id);
40
43
  });
41
44
  try {
42
45
  const info = await agent.listen();
43
46
  ++this.stats.tunnels;
47
+ // Call the onTunnelCreated hook
48
+ if (this.opt.onTunnelCreated) {
49
+ this.opt.onTunnelCreated({ domain, id, url });
50
+ }
44
51
  return {
52
+ domain,
45
53
  id: id,
46
54
  maxConnCount: maxSockets,
47
55
  port: info.port,
56
+ url,
48
57
  };
49
58
  }
50
59
  catch (err) {
@@ -57,9 +66,17 @@ export class ClientManager {
57
66
  const client = this.clients.get(id);
58
67
  if (!client)
59
68
  return;
69
+ const tunnelInfo = this.clientTunnelInfo.get(id);
70
+ const domain = tunnelInfo?.domain || '';
71
+ const url = tunnelInfo?.url || '';
60
72
  --this.stats.tunnels;
61
73
  this.clients.delete(id);
74
+ this.clientTunnelInfo.delete(id);
62
75
  client.close();
76
+ // Call the onTunnelClosed hook
77
+ if (this.opt.onTunnelClosed) {
78
+ this.opt.onTunnelClosed({ domain, id, url });
79
+ }
63
80
  }
64
81
  }
65
82
  //# sourceMappingURL=ClientManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClientManager.js","sourceRoot":"","sources":["../../src/server/ClientManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAIzC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAa/C,MAAM,OAAO,aAAa;IACjB,KAAK,CAAsB;IAC1B,OAAO,CAAsB;IAC7B,GAAG,CAAiB;IACpB,GAAG,CAAuB;IAElC,YAAY,MAA4B,EAAE;QACxC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACvC,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,WAAoB;QAClC,IAAI,EAAU,CAAC;QACf,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YAClD,EAAE,GAAG,WAAW,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QACpB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC;QAC1C,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC;YAC5B,QAAQ,EAAE,EAAE;YACZ,aAAa,EAAE,EAAE;YACjB,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY;SACpC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QAEzC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QAE7B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC;YAClC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;YACrB,OAAO;gBACL,EAAE,EAAE,EAAE;gBACN,YAAY,EAAE,UAAU;gBACxB,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACtB,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;IAED,YAAY,CAAC,EAAU;QACrB,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"ClientManager.js","sourceRoot":"","sources":["../../src/server/ClientManager.ts"],"names":[],"mappings":"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"}
@@ -8,20 +8,20 @@ describe('ClientManager', () => {
8
8
  });
9
9
  it('should create a new client with random id', async () => {
10
10
  const manager = new ClientManager();
11
- const client = await manager.newClient();
11
+ const client = await manager.newClient(undefined, 'http://test.example.com', 'example.com');
12
12
  expect(manager.hasClient(client.id)).toBe(true);
13
13
  manager.removeClient(client.id);
14
14
  });
15
15
  it('should create a new client with id', async () => {
16
16
  const manager = new ClientManager();
17
- await manager.newClient('foobar');
17
+ await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
18
18
  expect(manager.hasClient('foobar')).toBe(true);
19
19
  manager.removeClient('foobar');
20
20
  });
21
21
  it('should create a new client with random id if previous exists', async () => {
22
22
  const manager = new ClientManager();
23
- const clientA = await manager.newClient('foobar');
24
- const clientB = await manager.newClient('foobar');
23
+ const clientA = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
24
+ const clientB = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
25
25
  expect(clientA.id).toBe('foobar');
26
26
  expect(manager.hasClient(clientB.id)).toBe(true);
27
27
  expect(clientB.id).not.toBe(clientA.id);
@@ -30,7 +30,7 @@ describe('ClientManager', () => {
30
30
  });
31
31
  it('should remove client once it goes offline', async () => {
32
32
  const manager = new ClientManager();
33
- const client = await manager.newClient('foobar');
33
+ const client = await manager.newClient('foobar', 'http://foobar.example.com', 'example.com');
34
34
  const socket = await new Promise((resolve) => {
35
35
  const netClient = net.createConnection({ port: client.port }, () => {
36
36
  resolve(netClient);
@@ -47,8 +47,8 @@ describe('ClientManager', () => {
47
47
  }, 5000);
48
48
  it('should remove correct client once it goes offline', async () => {
49
49
  const manager = new ClientManager();
50
- const clientFoo = await manager.newClient('foo');
51
- await manager.newClient('bar');
50
+ const clientFoo = await manager.newClient('foo', 'http://foo.example.com', 'example.com');
51
+ await manager.newClient('bar', 'http://bar.example.com', 'example.com');
52
52
  const socket = await new Promise((resolve) => {
53
53
  const netClient = net.createConnection({ port: clientFoo.port }, () => {
54
54
  resolve(netClient);
@@ -64,7 +64,7 @@ describe('ClientManager', () => {
64
64
  }, 5000);
65
65
  it('should remove clients if they do not connect within 5 seconds', async () => {
66
66
  const manager = new ClientManager();
67
- await manager.newClient('foo');
67
+ await manager.newClient('foo', 'http://foo.example.com', 'example.com');
68
68
  expect(manager.hasClient('foo')).toBe(true);
69
69
  // wait past grace period (1s)
70
70
  await new Promise(resolve => setTimeout(resolve, 1500));
@@ -1 +1 @@
1
- {"version":3,"file":"ClientManager.spec.js","sourceRoot":"","sources":["../../src/server/ClientManager.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ClientManager.spec.js","sourceRoot":"","sources":["../../src/server/ClientManager.spec.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
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';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC3H,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACnH,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC3H,OAAO,EAAE,KAAK,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAsB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAiD,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,YAAY,EAA0C,MAAM,aAAa,CAAC;AACnF,OAAO,EAAE,WAAW,EAA8E,MAAM,kBAAkB,CAAC;AAC3H,OAAO,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAsB,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAkE,MAAM,oBAAoB,CAAC;AACnH,OAAO,EAAE,YAAY,EAA8E,MAAM,aAAa,CAAC;AACvH,OAAO,EAAE,WAAW,EAA8E,MAAM,kBAAkB,CAAC;AAC3H,OAAO,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -3,12 +3,38 @@ import { TunnelServer } from './TunnelServer.js';
3
3
  export interface PipenetServer extends http.Server {
4
4
  tunnelServer?: TunnelServer;
5
5
  }
6
- export interface ServerOptions {
6
+ export interface RequestInfo {
7
+ headers: Record<string, string | string[] | undefined>;
8
+ method: string;
9
+ path: string;
10
+ remoteAddress?: string;
11
+ tunnelId: string;
12
+ }
13
+ export interface ServerHooks {
14
+ /**
15
+ * Called when a request is proxied through a tunnel
16
+ */
17
+ onRequest?: (request: RequestInfo) => void;
18
+ /**
19
+ * Called when a tunnel is closed
20
+ */
21
+ onTunnelClosed?: (tunnel: TunnelInfo) => void;
22
+ /**
23
+ * Called when a new tunnel is created
24
+ */
25
+ onTunnelCreated?: (tunnel: TunnelInfo) => void;
26
+ }
27
+ export interface ServerOptions extends ServerHooks {
7
28
  domains?: string[];
8
29
  landing?: string;
9
30
  maxTcpSockets?: number;
10
31
  secure?: boolean;
11
32
  tunnelPort?: number;
12
33
  }
34
+ export interface TunnelInfo {
35
+ domain: string;
36
+ id: string;
37
+ url: string;
38
+ }
13
39
  export declare function createServer(opt?: ServerOptions): PipenetServer;
14
40
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIjD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,MAAM;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,GAAG,GAAE,aAAkB,GAAG,aAAa,CA0KnE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAOxB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIjD,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,MAAM;IAChD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAE9C;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,YAAY,CAAC,GAAG,GAAE,aAAkB,GAAG,aAAa,CAmMnE"}
@@ -56,10 +56,18 @@ export function createServer(opt = {}) {
56
56
  });
57
57
  app.use(router.routes());
58
58
  app.use(router.allowedMethods());
59
+ // Helper to extract domain from host (strips port if present)
60
+ const getDomain = (host) => {
61
+ // Remove port if present (e.g., "localhost:3000" -> "localhost")
62
+ return host.split(':')[0];
63
+ };
64
+ // Helper to build the tunnel URL
65
+ const buildUrl = (id, host) => {
66
+ return schema + '://' + id + '.' + host;
67
+ };
59
68
  // Helper to build response with tunnel port if configured
60
- const buildResponse = (info, host) => {
61
- const url = schema + '://' + info.id + '.' + host;
62
- const response = { ...info, url };
69
+ const buildResponse = (info) => {
70
+ const response = { ...info };
63
71
  // If using shared tunnel server, override port and add sharedTunnel flag
64
72
  if (tunnelPort) {
65
73
  response.port = tunnelPort;
@@ -76,9 +84,11 @@ export function createServer(opt = {}) {
76
84
  const isNewClientRequest = ctx.query['new'] !== undefined;
77
85
  if (isNewClientRequest) {
78
86
  const reqId = hri.random();
87
+ const domain = getDomain(ctx.request.host);
88
+ const url = buildUrl(reqId, ctx.request.host);
79
89
  log('making new client with id %s', reqId);
80
- const info = await manager.newClient(reqId);
81
- ctx.body = buildResponse(info, ctx.request.host);
90
+ const info = await manager.newClient(reqId, url, domain);
91
+ ctx.body = buildResponse(info);
82
92
  return;
83
93
  }
84
94
  ctx.redirect(landingPage);
@@ -96,9 +106,11 @@ export function createServer(opt = {}) {
96
106
  ctx.body = { message: msg };
97
107
  return;
98
108
  }
109
+ const domain = getDomain(ctx.request.host);
110
+ const url = buildUrl(reqId, ctx.request.host);
99
111
  log('making new client with id %s', reqId);
100
- const info = await manager.newClient(reqId);
101
- ctx.body = buildResponse(info, ctx.request.host);
112
+ const info = await manager.newClient(reqId, url, domain);
113
+ ctx.body = buildResponse(info);
102
114
  });
103
115
  const server = http.createServer();
104
116
  server.tunnelServer = tunnelServer;
@@ -121,6 +133,16 @@ export function createServer(opt = {}) {
121
133
  res.end('404');
122
134
  return;
123
135
  }
136
+ // Call the onRequest hook
137
+ if (opt.onRequest) {
138
+ opt.onRequest({
139
+ headers: req.headers,
140
+ method: req.method || 'GET',
141
+ path: req.url || '/',
142
+ remoteAddress: req.socket.remoteAddress,
143
+ tunnelId: clientId,
144
+ });
145
+ }
124
146
  client.handleRequest(req, res);
125
147
  });
126
148
  server.on('upgrade', (req, socket) => {
@@ -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":"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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":"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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.0",
5
5
  "type": "module",
6
6
  "main": "./dist/pipenet.js",
7
7
  "types": "./dist/pipenet.d.ts",
@@ -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
  });
@@ -14,7 +14,32 @@ export interface PipenetServer extends http.Server {
14
14
  tunnelServer?: TunnelServer;
15
15
  }
16
16
 
17
- export interface ServerOptions {
17
+ export interface RequestInfo {
18
+ headers: Record<string, string | string[] | undefined>;
19
+ method: string;
20
+ path: string;
21
+ remoteAddress?: string;
22
+ tunnelId: string;
23
+ }
24
+
25
+ export interface ServerHooks {
26
+ /**
27
+ * Called when a request is proxied through a tunnel
28
+ */
29
+ onRequest?: (request: RequestInfo) => void;
30
+
31
+ /**
32
+ * Called when a tunnel is closed
33
+ */
34
+ onTunnelClosed?: (tunnel: TunnelInfo) => void;
35
+
36
+ /**
37
+ * Called when a new tunnel is created
38
+ */
39
+ onTunnelCreated?: (tunnel: TunnelInfo) => void;
40
+ }
41
+
42
+ export interface ServerOptions extends ServerHooks {
18
43
  domains?: string[];
19
44
  landing?: string;
20
45
  maxTcpSockets?: number;
@@ -22,6 +47,12 @@ export interface ServerOptions {
22
47
  tunnelPort?: number;
23
48
  }
24
49
 
50
+ export interface TunnelInfo {
51
+ domain: string;
52
+ id: string;
53
+ url: string;
54
+ }
55
+
25
56
  export function createServer(opt: ServerOptions = {}): PipenetServer {
26
57
  const validHosts = opt.domains && opt.domains.length > 0 ? opt.domains : undefined;
27
58
  const myTldjs = tldjs.fromUserSettings({ validHosts });
@@ -84,10 +115,20 @@ export function createServer(opt: ServerOptions = {}): PipenetServer {
84
115
  app.use(router.routes());
85
116
  app.use(router.allowedMethods());
86
117
 
118
+ // Helper to extract domain from host (strips port if present)
119
+ const getDomain = (host: string) => {
120
+ // Remove port if present (e.g., "localhost:3000" -> "localhost")
121
+ return host.split(':')[0];
122
+ };
123
+
124
+ // Helper to build the tunnel URL
125
+ const buildUrl = (id: string, host: string) => {
126
+ return schema + '://' + id + '.' + host;
127
+ };
128
+
87
129
  // Helper to build response with tunnel port if configured
88
- const buildResponse = (info: { id: string; maxConnCount?: number; port: number; }, host: string) => {
89
- const url = schema + '://' + info.id + '.' + host;
90
- const response: Record<string, unknown> = { ...info, url };
130
+ const buildResponse = (info: { domain: string; id: string; maxConnCount?: number; port: number; url: string }) => {
131
+ const response: Record<string, unknown> = { ...info };
91
132
  // If using shared tunnel server, override port and add sharedTunnel flag
92
133
  if (tunnelPort) {
93
134
  response.port = tunnelPort;
@@ -107,10 +148,12 @@ export function createServer(opt: ServerOptions = {}): PipenetServer {
107
148
  const isNewClientRequest = ctx.query['new'] !== undefined;
108
149
  if (isNewClientRequest) {
109
150
  const reqId = hri.random();
151
+ const domain = getDomain(ctx.request.host);
152
+ const url = buildUrl(reqId, ctx.request.host);
110
153
  log('making new client with id %s', reqId);
111
- const info = await manager.newClient(reqId);
154
+ const info = await manager.newClient(reqId, url, domain);
112
155
 
113
- ctx.body = buildResponse(info, ctx.request.host);
156
+ ctx.body = buildResponse(info);
114
157
  return;
115
158
  }
116
159
 
@@ -134,10 +177,12 @@ export function createServer(opt: ServerOptions = {}): PipenetServer {
134
177
  return;
135
178
  }
136
179
 
180
+ const domain = getDomain(ctx.request.host);
181
+ const url = buildUrl(reqId, ctx.request.host);
137
182
  log('making new client with id %s', reqId);
138
- const info = await manager.newClient(reqId);
183
+ const info = await manager.newClient(reqId, url, domain);
139
184
 
140
- ctx.body = buildResponse(info, ctx.request.host);
185
+ ctx.body = buildResponse(info);
141
186
  });
142
187
 
143
188
  const server: PipenetServer = http.createServer();
@@ -166,6 +211,17 @@ export function createServer(opt: ServerOptions = {}): PipenetServer {
166
211
  return;
167
212
  }
168
213
 
214
+ // Call the onRequest hook
215
+ if (opt.onRequest) {
216
+ opt.onRequest({
217
+ headers: req.headers,
218
+ method: req.method || 'GET',
219
+ path: req.url || '/',
220
+ remoteAddress: req.socket.remoteAddress,
221
+ tunnelId: clientId,
222
+ });
223
+ }
224
+
169
225
  client.handleRequest(req, res);
170
226
  });
171
227