pipenet 1.4.0 → 1.4.2

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
@@ -1,6 +1,17 @@
1
1
  # pipenet
2
2
 
3
- Expose your local server to the public internet instantly
3
+ Expose your local server to the public internet instantly.
4
+
5
+ ## Supported Protocols
6
+
7
+ pipenet tunnels any HTTP-based traffic to your local server:
8
+
9
+ | Protocol | Supported | Notes |
10
+ | -------- | --------- | ----- |
11
+ | HTTP/HTTPS | ✅ | Standard request/response |
12
+ | WebSocket | ✅ | Full duplex communication via HTTP upgrade |
13
+ | SSE (Server-Sent Events) | ✅ | Long-lived HTTP connections |
14
+ | HTTP Streaming | ✅ | Chunked transfer encoding |
4
15
 
5
16
  ## Installation
6
17
 
@@ -212,6 +223,27 @@ pipenet is a modernized fork of [localtunnel](https://github.com/localtunnel/loc
212
223
 
213
224
  **Modern JavaScript**: pipenet uses ES modules and is written in TypeScript, providing better IDE support, type safety, and compatibility with modern JavaScript tooling.
214
225
 
226
+ ## pipenet vs zrok
227
+
228
+ [zrok](https://zrok.io/) is a powerful tunneling solution with SDK support for Go, Python, and Node.js. However, zrok SDKs require the environment to be initialized via the CLI first - you can't just `npm install` and start tunneling.
229
+
230
+ pipenet is designed for zero-setup embedding:
231
+
232
+ ```js
233
+ import { pipenet } from 'pipenet';
234
+
235
+ const tunnel = await pipenet({ port: 3000 });
236
+ console.log(tunnel.url);
237
+ ```
238
+
239
+ No CLI initialization, no external processes, no daemon - just a pure JavaScript library that works out of the box. This makes pipenet ideal for:
240
+
241
+ - **CLI tools** that need tunneling as a feature (e.g., `mcp-proxy --tunnel`)
242
+ - **Test suites** that need ephemeral public URLs
243
+ - **Scripts** that should "just work" without setup steps
244
+
245
+ If you need advanced features like TCP/UDP tunneling, identity management, or a managed SaaS, zrok is an excellent choice.
246
+
215
247
  ## Acknowledgments
216
248
 
217
249
  pipenet is based on [localtunnel](https://github.com/localtunnel/localtunnel).
@@ -1 +1 @@
1
- {"version":3,"file":"Tunnel.d.ts","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAwB,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,aAAa;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+BD,qBAAa,MAAO,SAAQ,YAAY;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;gBAER,IAAI,GAAE,aAAkB;IASpC,KAAK,IAAI,IAAI;IAKb,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAmBrC,OAAO,CAAC,UAAU;IAqDlB,OAAO,CAAC,QAAQ;IAwBhB,OAAO,CAAC,KAAK;CAmCd"}
1
+ {"version":3,"file":"Tunnel.d.ts","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,aAAa,EAAwB,MAAM,oBAAoB,CAAC;AAIzE,MAAM,WAAW,aAAa;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA+BD,qBAAa,MAAO,SAAQ,YAAY;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;gBAER,IAAI,GAAE,aAAkB;IASpC,KAAK,IAAI,IAAI;IAKb,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI;IAmBrC,OAAO,CAAC,UAAU;IAkElB,OAAO,CAAC,QAAQ;IAwBhB,OAAO,CAAC,KAAK;CAiCd"}
package/dist/Tunnel.js CHANGED
@@ -48,6 +48,7 @@ export class Tunnel extends EventEmitter {
48
48
  this.emit('error', err);
49
49
  });
50
50
  let tunnelCount = 0;
51
+ const tunnelHandlers = new Map();
51
52
  this.tunnelCluster.on('open', (tunnel) => {
52
53
  tunnelCount++;
53
54
  log('tunnel open [total: %d]', tunnelCount);
@@ -58,14 +59,24 @@ export class Tunnel extends EventEmitter {
58
59
  closeHandler();
59
60
  return;
60
61
  }
62
+ tunnelHandlers.set(tunnel, closeHandler);
61
63
  this.once('close', closeHandler);
62
64
  tunnel.once('close', () => {
65
+ tunnelHandlers.delete(tunnel);
63
66
  this.removeListener('close', closeHandler);
64
67
  });
65
68
  });
66
- this.tunnelCluster.on('dead', () => {
69
+ this.tunnelCluster.on('dead', (deadSocket) => {
67
70
  tunnelCount--;
68
71
  log('tunnel dead [total: %d]', tunnelCount);
72
+ // Eagerly remove the close handler for the dead tunnel.
73
+ // Without this, the handler lingers until the socket's async
74
+ // 'close' event fires, causing listener accumulation.
75
+ if (deadSocket && tunnelHandlers.has(deadSocket)) {
76
+ const handler = tunnelHandlers.get(deadSocket);
77
+ tunnelHandlers.delete(deadSocket);
78
+ this.removeListener('close', handler);
79
+ }
69
80
  if (this.closed) {
70
81
  return;
71
82
  }
@@ -116,13 +127,13 @@ export class Tunnel extends EventEmitter {
116
127
  .then((res) => {
117
128
  const body = res.data;
118
129
  log('got tunnel information', res.data);
119
- if (res.status !== 200) {
120
- const err = new Error(body?.message || 'pipenet server returned an error, please try again');
121
- return cb(err);
122
- }
123
130
  cb(null, getInfo(body));
124
131
  })
125
132
  .catch((err) => {
133
+ if (err.response && err.response.status >= 400 && err.response.status < 500) {
134
+ const message = err.response.data?.message || err.message;
135
+ return cb(new Error(message));
136
+ }
126
137
  log(`tunnel server offline: ${err.message}, retry 1s`);
127
138
  setTimeout(getUrl, 1000);
128
139
  });
@@ -1 +1 @@
1
- {"version":3,"file":"Tunnel.js","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Tunnel.js","sourceRoot":"","sources":["../src/Tunnel.ts"],"names":[],"mappings":"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"}
@@ -35,7 +35,7 @@ export class TunnelCluster extends EventEmitter {
35
35
  const connLocal = () => {
36
36
  if (remote.destroyed) {
37
37
  log('remote destroyed');
38
- this.emit('dead');
38
+ this.emit('dead', remote);
39
39
  return;
40
40
  }
41
41
  log('connecting locally to %s://%s:%d', localProtocol, localHost, localPort);
@@ -55,7 +55,7 @@ export class TunnelCluster extends EventEmitter {
55
55
  : net.connect({ host: localHost, port: localPort });
56
56
  const remoteClose = () => {
57
57
  log('remote close');
58
- this.emit('dead');
58
+ this.emit('dead', remote);
59
59
  local.end();
60
60
  };
61
61
  remote.once('close', remoteClose);
@@ -1 +1 @@
1
- {"version":3,"file":"TunnelCluster.js","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TunnelCluster.js","sourceRoot":"","sources":["../src/TunnelCluster.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import axios from 'axios';
2
+ import { EventEmitter } from 'events';
2
3
  import http from 'http';
3
4
  import { afterAll, beforeAll, describe, expect, it } from 'vitest';
4
5
  import { pipenet } from './pipenet.js';
@@ -67,6 +68,12 @@ describe('pipenet', () => {
67
68
  tunnel.close();
68
69
  });
69
70
  });
71
+ describe('error handling', () => {
72
+ it('should include server error message', async () => {
73
+ const result = pipenet(fakePort, { host, subdomain: 'no' });
74
+ await expect(result).rejects.toThrow('Invalid subdomain');
75
+ });
76
+ });
70
77
  describe('custom headers', () => {
71
78
  it('should accept custom headers option', async () => {
72
79
  const customHeaders = {
@@ -78,5 +85,21 @@ describe('pipenet', () => {
78
85
  tunnel.close();
79
86
  });
80
87
  });
88
+ it('does not leak close listeners across tunnel reconnections', async () => {
89
+ const tunnel = await pipenet(fakePort, { host });
90
+ const cluster = tunnel.tunnelCluster;
91
+ const before = tunnel.listenerCount('close');
92
+ // Force rapid reconnection cycles by emitting open→dead on the cluster.
93
+ for (let i = 0; i < 20; i++) {
94
+ const fakeSocket = new EventEmitter();
95
+ fakeSocket.destroy = () => { };
96
+ cluster.emit('open', fakeSocket);
97
+ cluster.emit('dead', fakeSocket);
98
+ }
99
+ // Without the fix, 20 close handlers would accumulate.
100
+ // With eager cleanup, count should not grow.
101
+ expect(tunnel.listenerCount('close')).toBe(before);
102
+ tunnel.close();
103
+ });
81
104
  });
82
105
  //# sourceMappingURL=pipenet.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipenet.spec.js","sourceRoot":"","sources":["../src/pipenet.spec.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEnE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,IAAY,CAAC;IACjB,IAAI,QAAgB,CAAC;IACrB,IAAI,YAAyB,CAAC;IAE9B,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;IAExC,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,oDAAoD;QACpD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;gBACrC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC5B,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;YACH,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE;gBACtB,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,EAAiB,CAAC;gBAClD,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;gBACrB,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,0CAA0C;QAC1C,YAAY,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACxD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE;gBACvB,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,EAAiB,CAAC;gBACnD,IAAI,GAAG,oBAAoB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACvC,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,GAAG,EAAE;QACZ,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,YAAY,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEL,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAI,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAExC,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,aAAa,SAAS,oBAAoB,CAAC,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;YAErE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;YACnD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;YAErE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;YACnD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,aAAa,GAAG;gBACpB,YAAY,EAAE,iBAAiB;gBAC/B,iBAAiB,EAAE,YAAY;aAChC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;YACrE,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AAEH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"pipenet.spec.js","sourceRoot":"","sources":["../src/pipenet.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.0",
4
+ "version": "1.4.2",
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
- import axios from 'axios';
1
+ import axios, { AxiosError } 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
  }
@@ -185,15 +199,13 @@ export class Tunnel extends EventEmitter {
185
199
  .then((res) => {
186
200
  const body = res.data;
187
201
  log('got tunnel information', res.data);
188
- if (res.status !== 200) {
189
- const err = new Error(
190
- body?.message || 'pipenet server returned an error, please try again'
191
- );
192
- return cb(err);
193
- }
194
202
  cb(null, getInfo(body));
195
203
  })
196
- .catch((err: Error) => {
204
+ .catch((err: AxiosError<ServerResponse>) => {
205
+ if (err.response && err.response.status >= 400 && err.response.status < 500) {
206
+ const message = err.response.data?.message || err.message;
207
+ return cb(new Error(message));
208
+ }
197
209
  log(`tunnel server offline: ${err.message}, retry 1s`);
198
210
  setTimeout(getUrl, 1000);
199
211
  });
@@ -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
 
@@ -84,6 +85,13 @@ describe('--local-host 127.0.0.1', () => {
84
85
  });
85
86
  });
86
87
 
88
+ describe('error handling', () => {
89
+ it('should include server error message', async () => {
90
+ const result = pipenet(fakePort, { host, subdomain: 'no' });
91
+ await expect(result).rejects.toThrow('Invalid subdomain');
92
+ });
93
+ });
94
+
87
95
  describe('custom headers', () => {
88
96
  it('should accept custom headers option', async () => {
89
97
  const customHeaders = {
@@ -96,4 +104,24 @@ describe('custom headers', () => {
96
104
  });
97
105
  });
98
106
 
107
+ it('does not leak close listeners across tunnel reconnections', async () => {
108
+ const tunnel = await pipenet(fakePort, { host });
109
+ const cluster = tunnel.tunnelCluster!;
110
+
111
+ const before = tunnel.listenerCount('close');
112
+
113
+ // Force rapid reconnection cycles by emitting open→dead on the cluster.
114
+ for (let i = 0; i < 20; i++) {
115
+ const fakeSocket = new EventEmitter() as { destroy: () => void } & EventEmitter;
116
+ fakeSocket.destroy = () => {};
117
+ cluster.emit('open', fakeSocket);
118
+ cluster.emit('dead', fakeSocket);
119
+ }
120
+
121
+ // Without the fix, 20 close handlers would accumulate.
122
+ // With eager cleanup, count should not grow.
123
+ expect(tunnel.listenerCount('close')).toBe(before);
124
+ tunnel.close();
125
+ });
126
+
99
127
  });