# https://github.com/punkpeye/pipenet 项目说明书

生成时间：2026-06-14 03:16:20 UTC

## 目录

- [概述与系统架构](#page-overview)
- [客户端 API 与 CLI 使用](#page-client)
- [服务器部署与云端模式](#page-server)
- [运维、故障模式与生命周期事件](#page-operations)

<a id='page-overview'></a>

## 概述与系统架构

### 相关页面

相关主题：[客户端 API 与 CLI 使用](#page-client), [服务器部署与云端模式](#page-server)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)
- [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- [src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)
- [src/HeaderHostTransformer.ts](https://github.com/punkpeye/pipenet/blob/main/src/HeaderHostTransformer.ts)
- [src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- [src/server/Client.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/Client.ts)
- [src/server/ClientManager.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.ts)
- [src/server/TunnelServer.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/TunnelServer.ts)
- [package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)
- [vitest.config.ts](https://github.com/punkpeye/pipenet/blob/main/vitest.config.ts)
- [README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
</details>

# 概述与系统架构

## 一、项目定位与设计目标

pipenet 是一款将本地 HTTP 服务即时暴露到公网的隧道代理工具，由 [glama.ai](https://glama.ai) 开发并开源。其核心目标是为本地运行的 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 服务器提供零配置的公网可达能力，该能力已集成到 [mcp-proxy](https://github.com/punkpeye/mcp-proxy) 项目中。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)

项目支持任意基于 HTTP 的协议，包括 HTTP/HTTPS 请求响应、WebSocket 全双工通信、Server-Sent Events 长连接以及分块传输（HTTP Streaming）。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)

相较于其前体 [localtunnel](https://github.com/localtunnel/localtunnel)，pipenet 提供了三项关键差异：云部署下的单端口模式（`--tunnel-port`）、多域名支持（`--domain` 可重复指定）、以及完全的 TypeScript + ESM 重写并附带完整类型定义。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)

## 二、运行时拓扑与数据流

pipenet 同时提供客户端与服务器两端代码，二者通过 npm 子导出分离：根导出 `./` 暴露 `pipenet`、`Tunnel`、`TunnelCluster`，`./server` 暴露 `createServer` 工厂。资料来源：[package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)

整体数据流如下：

```mermaid
sequenceDiagram
    participant U as 互联网用户
    participant S as pipenet 服务器 (Koa)
    participant TS as TunnelServer (可选)
    participant CM as ClientManager
    participant C as 本地 pipenet 客户端
    participant L as 本地 HTTP 服务
    U->>S: HTTP 请求 (子域名)
    S->>CM: 路由到对应 Client
    CM->>C: 通过长连接回传
    C->>L: 转发到本地 port
    L-->>C: HTTP 响应
    C-->>S: 原路返回
    S-->>U: 返回响应
```

### 客户端组件

- 入口函数 `pipenet(port | opts, [cb])` 创建 `Tunnel` 实例，未指定 `host` 时默认指向 `https://pipenet.dev`。资料来源：[src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts) [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- `Tunnel` 通过 `_init` 流程向远端注册，获取子域名、最大连接数 (`maxConn`)、远端地址/端口后建立 `TunnelCluster`。资料来源：[src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- `TunnelCluster` 与远端维持长连接，使用 `HeaderHostTransformer` 改写 `Host` 头，并通过 `pump` 在 `maxConn` 条 socket 上并行转发公网到本地的流量。资料来源：[src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)

### 服务器组件

- `createServer(opt)` 工厂创建 `PipenetServer`，内部实例化 `ClientManager` 与可选的 `TunnelServer`（仅在传入 `tunnelPort` 时启用）。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- `ClientManager` 负责子域名前缀解析、客户端注册与统计信息维护，并按需创建 `Client` 与 `TunnelAgent`。资料来源：[src/server/ClientManager.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.ts)
- `Client` 通过 `pump` 将 `http.IncomingMessage` 与 `TunnelAgent` 提供的 socket 双向桥接，并提供 1 秒离线宽限期（`graceTimeout`）。资料来源：[src/server/Client.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/Client.ts)

## 三、运行模式与配置接口

pipenet 支持两种主要运行模式：

1. **默认模式**：每个客户端在远端分配一个随机 TCP 端口，适用于本地开发与单机部署。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
2. **共享隧道模式**：服务器启动时传入 `--tunnel-port`，所有客户端共享同一固定端口，便于在 Docker、fly.io、Kubernetes 等仅暴露有限端口的容器环境中部署。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md) [src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)

配置入口分为两端：

- 服务器通过 `ServerOptions` 传入 `domains`、`landing`、`maxTcpSockets`、`secure`、`tunnelPort` 等字段。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- 客户端通过 `TunnelOptions` 配置 `port`、`subdomain`、`localHost`、`localHttps`、`localCert/Key/Ca`、`allowInvalidCert` 等字段。资料来源：[src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts) [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)

CLI 通过 `bin` 字段注册 `pipenet` 入口，提供 `client` 与 `server` 两个子命令；服务器也可通过 `npm run start:server` 启动。资料来源：[package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)

## 四、依赖、测试与版本演进

项目声明 `engines.node >= 22.0.0`，使用 `pnpm@10.28.0` 作为包管理器，并通过 `semantic-release` 自动发布。核心依赖包括 `axios`（注册请求）、`koa`+`koa-router`（服务器路由）、`ws`+`pump`（流桥接）、`yargs`（CLI 解析）、`tldjs`（子域名解析）、`debug`（结构化日志）、`human-readable-ids`（默认子域名前缀生成）。资料来源：[package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)

测试使用 `vitest`，覆盖 `src/**/*.spec.ts`，并显式排除 `dist` 与 `server` 目录中可能引入的端到端依赖；`build` 调用 `tsc`，`lint` 脚本同时运行 `eslint` 与 `knip` 检测未使用代码。资料来源：[package.json](https://github.com/punkpeye/pipenet/blob/main/package.json) [vitest.config.ts](https://github.com/punkpeye/pipenet/blob/main/vitest.config.ts)

近期版本变更体现了架构持续演进：

| 版本 | 关键变更 | 资料来源 |
| ---- | -------- | -------- |
| v1.2.0 | 支持多域名（`--domain` 多次使用） | [Release](https://github.com/punkpeye/pipenet/releases/tag/v1.2.0) |
| v1.3.0 | 新增 `address` 选项与共享隧道服务器 | [Release](https://github.com/punkpeye/pipenet/releases/tag/v1.3.0) |
| v1.4.0 | 新增 `hooks` 扩展点 | [Release](https://github.com/punkpeye/pipenet/releases/tag/v1.4.0) |
| v1.4.1 | 修复快速重连时的 close listener 泄漏 | [Release](https://github.com/punkpeye/pipenet/releases/tag/v1.4.1) |
| v1.4.2 | 收到 4XX 响应时中止隧道创建 | [Release](https://github.com/punkpeye/pipenet/releases/tag/v1.4.2) |

> 社区提示：早期版本（v1.0.1）的 `npx pipenet client --port 3303` 存在返回 404 后立即退出的问题（见 [issue #1](https://github.com/punkpeye/pipenet/issues/1)）。该问题已在 1.2.x – 1.4.x 系列中得到修复：v1.4.2 增加了 4XX 中止保护，v1.4.1 修复了重连泄漏，CLI 进程因此可以稳定保持为前台服务。

## See Also

- 客户端与服务器代码索引：[src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)、[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- 协议支持与 CLI 用法：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
- 完整版本变更：[GitHub Releases](https://github.com/punkpeye/pipenet/releases)

---

<a id='page-client'></a>

## 客户端 API 与 CLI 使用

### 相关页面

相关主题：[概述与系统架构](#page-overview), [运维、故障模式与生命周期事件](#page-operations)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/cli.ts](https://github.com/punkpeye/pipenet/blob/main/src/cli.ts)
- [src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)
- [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- [src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)
- [src/HeaderHostTransformer.ts](https://github.com/punkpeye/pipenet/blob/main/src/HeaderHostTransformer.ts)
- [src/pipenet.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.spec.ts)
- [package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)
- [README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
</details>

# 客户端 API 与 CLI 使用

## 概述

pipenet 客户端组件负责将本地 HTTP 服务透明地暴露到公网，支持 HTTP/HTTPS、WebSocket、SSE（Server-Sent Events）以及 HTTP Streaming 协议 [README.md](README.md)。它既可以作为一个独立的命令行工具（`pipenet client`）使用，也可以作为一个无依赖的 JavaScript 库被嵌入到测试脚本、CLI 工具（如 `mcp-proxy`）或自动化流程中 [README.md](README.md)。客户端通过 HTTP 请求向 pipenet 服务器申请一个公共子域名，建立长连接隧道后将公网流量反向代理到本地端口 [src/Tunnel.ts](src/Tunnel.ts)。

## CLI 使用

通过 `npx` 或全局安装后即可调用 pipenet 命令行工具 [package.json](package.json)。CLI 入口在 `src/cli.ts` 中基于 `yargs` 解析参数，并使用 `pipenet()` API 启动隧道 [package.json](package.json)。

```bash
# 暴露本地端口 3000
npx pipenet client --port 3000

# 请求指定子域名
npx pipenet client --port 3000 --subdomain myapp

# 使用自建隧道服务器
npx pipenet client --port 3000 --host https://your-tunnel-server.com
```

CLI 主要选项包括：

| 选项 | 说明 |
| --- | --- |
| `--port` | 本地服务监听的端口（必填） |
| `--subdomain` | 自定义子域名，长度需在 4–63 个字符之间 |
| `--host` | pipenet 服务器地址，默认指向 `pipenet.dev` |
| `--local-https` | 本地服务使用 HTTPS |
| `--allow-invalid-cert` | 跳过本地 HTTPS 证书校验 |

## 编程式 API

`pipenet()` 是客户端的核心入口，定义于 [src/pipenet.ts](src/pipenet.ts)。它支持函数重载以兼容旧的 Node 回调风格，并统一返回 `Promise<Tunnel>`：

```js
import { pipenet } from 'pipenet';

// Promise 风格
const tunnel = await pipenet({ port: 3000, host: 'https://loud-shrimp-92.pipenet.dev' });
console.log(tunnel.url);

// 回调风格
pipenet({ port: 3000 }, (err, tunnel) => {
  if (err) return console.error(err);
  console.log(tunnel.url);
});
```

函数内部会构造一个 `Tunnel` 实例并调用 `client.open()` 完成子域分配 [src/pipenet.ts](src/pipenet.ts)。`open()` 方法通过 `axios` 向 `${host}/` 发起 GET 请求（携带 `?new` 或指定的 `subdomain`），服务器返回 JSON 格式的 `TunnelInfo`，包含 `id`、`domain` 与 `url` 字段 [src/Tunnel.ts](src/Tunnel.ts)。

## Tunnel 实例与事件

成功建立隧道后，`Tunnel` 实例提供以下能力 [src/Tunnel.ts](src/Tunnel.ts)：

- **属性**：`url`（公网地址）、`clientId`、`cachedUrl`。
- **事件**：
  - `request`：每当有请求被代理时触发，回调参数包含 `method` 与 `path`。
  - `error`：隧道内部错误，例如本地连接断开。
  - `close`：隧道已关闭。
- **方法**：`close()` 用于主动关闭隧道并断开与服务器的长连接。

底层连接复用由 `TunnelCluster` 管理，它负责维护到隧道服务器的 TCP 长连接集合，并在每次新请求到达时建立到本地服务的临时 socket [src/TunnelCluster.ts](src/TunnelCluster.ts)。`HeaderHostTransformer` 会在转发时重写请求头中的 `Host` 字段，使其匹配本地服务的监听地址 [src/HeaderHostTransformer.ts](src/HeaderHostTransformer.ts)。

## 典型调用流程

```mermaid
sequenceDiagram
  participant CLI as CLI/JS 调用方
  participant C as Tunnel 客户端
  participant S as pipenet 服务器
  participant L as 本地服务

  CLI->>C: pipenet({ port: 3000 })
  C->>S: GET / (申请子域名)
  S-->>C: { id, domain, url }
  C-->>CLI: resolve(Tunnel)
  S->>C: 公网请求 → 建立到客户端的 TCP 连接
  C->>L: 反向代理到 localhost:3000
  L-->>C: 响应
  C-->>S: 透传响应回公网
```

## 常见问题与故障排查

社区中报告的最常见问题是 `npx pipenet client --port 3303` 出现 404 [Issue #1](https://github.com/punkpeye/pipenet/issues/1)。通常原因包括：

1. **本地端口无服务监听**：CLI 不会校验 `--port` 是否真实可用，需确保 `localhost:3303` 上已有进程运行。
2. **使用了错误的服务器地址**：部分用户配置了自建服务器但未正确开放入站流量。
3. **CLI 输出后立即退出**：必须保持进程前台运行，命令行没有内置 `daemon` 模式。

v1.4.2 版本专门修复了「在 4XX 响应时中止隧道创建」的逻辑，确保服务器返回错误（如子域名被占用）时不会无限重试 [v1.4.2](https://github.com/punkpeye/pipenet/releases/tag/v1.4.2)。v1.4.1 还修复了快速重连时 `close` 监听器泄漏的问题 [v1.4.1](https://github.com/punkpeye/pipenet/releases/tag/v1.4.1)。

## 测试与集成

`src/pipenet.spec.ts` 演示了如何在内置测试中启动本地 HTTP 服务器与本地 pipenet 服务器，再通过 `pipenet(fakePort, { host })` 创建隧道并断言返回的 URL 模式 [src/pipenet.spec.ts](src/pipenet.spec.ts)。这一模式可直接复用于需要临时公网 URL 的端到端测试场景。

## 参见

- [Server Configuration（服务器配置）](Server-Configuration)
- [Cloud Deployment（云部署指南）](Cloud-Deployment)
- [Tunnel Protocol Reference（隧道协议参考）](Tunnel-Protocol-Reference)

---

<a id='page-server'></a>

## 服务器部署与云端模式

### 相关页面

相关主题：[概述与系统架构](#page-overview), [运维、故障模式与生命周期事件](#page-operations)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- [src/server/TunnelServer.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/TunnelServer.ts)
- [src/server/ClientManager.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.ts)
- [src/server/TunnelAgent.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/TunnelAgent.ts)
- [src/server/index.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/index.ts)
- [src/server/server.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.spec.ts)
- [src/server/ClientManager.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.spec.ts)
- [src/server/TunnelAgent.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/TunnelAgent.spec.ts)
- [src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)
- [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- [src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)
- [package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)
- [README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
</details>

# 服务器部署与云端模式

## 概述与适用场景

`pipenet` 是一个用于将本地服务即时暴露到公网的隧道工具，它同时提供客户端 SDK 与服务端实现。本页重点说明如何以自托管方式部署 `pipenet` 服务端，以及在容器化云端环境（Docker、fly.io、Kubernetes 等仅暴露固定端口的场景）下应如何使用「共享单端口模式」运行服务端。

与 [localtunnel](https://github.com/localtunnel/localtunnel) 不同，`pipenet` 增加了 `--tunnel-port` 单端口模式，使其能够在云端容器中正常工作；同时原生 ESM、TypeScript 类型与多域名支持也是其相对于 `localtunnel` 的关键改进。资料来源：[README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)

服务端运行时要求 Node.js `>= 22.0.0`，核心依赖包括 `koa`、`koa-router`、`tldjs`、`yargs`、`axios` 等。资料来源：[package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)

## 服务端架构与核心组件

`createServer()` 是构建服务端实例的入口函数，它在内部组装了 Koa 路由器、客户端管理器以及（可选的）共享隧道服务器。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)

```mermaid
graph TB
    Browser[Public Browser] -->|HTTPS :443| K[Koa + Router]
    K -->|CORS + Routing| CM[ClientManager]
    CM --> TA[TunnelAgent]
    TA -->|HTTP/WS| Local[Local App :3000]
    K -.->|optional| TS[TunnelServer<br/>shared single port]
    Client[pipenet client] -->|TCP tunnel| TA
    Client -.->|cloud mode| TS
```

- **Koa 应用与路由器**：负责 HTTP/HTTPS 入口、CORS 预检（`OPTIONS` 204）、根路径重定向到落地页。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- **ClientManager**：根据请求的子域名解析目标隧道客户端，暴露 `newClient(id, url, domain)`、`hasClient(id)`、`removeClient(id)`、`stats.tunnels` 等 API。资料来源：[src/server/ClientManager.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.spec.ts)
- **TunnelAgent**：为每个客户端提供本地 TCP 监听器，封装 `listen()`、`createConnection()`、`destroy()` 等方法；通过 `maxTcpSockets` 控制最大并发 TCP 连接数。资料来源：[src/server/TunnelAgent.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/TunnelAgent.spec.ts)
- **TunnelServer（共享单端口隧道服务）**：当传入 `tunnelPort` 时被创建，所有客户端通过同一端口与服务器建立长连接，规避云端容器需逐个映射随机端口的限制。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)，[v1.3.0 release notes](https://github.com/punkpeye/pipenet/releases/tag/v1.3.0)

## 部署模式

### 标准模式（独立端口模式）

在传统 VPS 或开发机上，每个 `pipenet client` 启动后会在服务端随机占用一个 TCP 端口用于隧道回连。该模式与 `localtunnel` 默认行为一致，适合本地开发。客户端可通过 `pipenet({ port: 3000 })` 启动并自动获得形如 `https://<slug>.<host>` 的公网 URL。资料来源：[src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)，[src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)

### 云端单端口模式

在 Docker / fly.io / Kubernetes 等仅暴露少量端口的容器环境中，应启用 `--tunnel-port`：

```bash
# 服务端：暴露 443 给公网，并通过 3303 接收所有客户端的隧道长连接
npx pipenet server --port 443 --tunnel-port 3303

# 客户端：明确指向共享隧道端口
npx pipenet client --port 3000 --tunnel-port 3303
```

此模式下服务端会在内部创建 `TunnelServer`，并将其实例化引用传入 `ClientManager`；客户端的 `TunnelCluster` 通过 `sharedTunnel: true` 选项复用同一长连接。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)，[src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)

## 配置项、API 端点与运行验证

服务端的核心可配置项通过 `ServerOptions` 传递，主要包括 `domains`（允许的基础域名数组，用于子域名解析与归属校验）、`landing`（根路径重定向目标，默认 `https://pipenet.dev/`）、`secure`（生成 URL 时使用 `https://`）、`tunnelPort`（启用共享单端口模式）。资料来源：[src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)

`ServerHooks` 允许在客户端注册、请求、关闭等生命周期注入回调；这些能力随 v1.4.0 的 `add hooks` 提交加入。资料来源：[src/server/index.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/index.ts)，[v1.4.0 release notes](https://github.com/punkpeye/pipenet/releases/tag/v1.4.0)

运行自带测试可验证部署正确性：`npm test`（vitest）。`server.spec.ts` 会校验根路径重定向、自定义域名下的子域名合法性（必须小写、长度 4–63、`[a-z0-9-]`），以及 WebSocket Upgrade 握手。资料来源：[src/server/server.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.spec.ts)

## 常见问题与故障排查

- **子域名非法（HTTP 4XX）**：当请求的子域名长度不在 4–63 字符或包含非允许字符时，服务端会以 4XX 中止隧道创建。客户端对此做了 `abort tunnel creation on 4XX` 的修复（v1.4.2），并以错误回调形式向用户抛出 `message` 字段。资料来源：[src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)，[v1.4.2 release notes](https://github.com/punkpeye/pipenet/releases/tag/v1.4.2)
- **快速重连导致监听器泄漏**：v1.4.1 修复了快速重连场景下 `close` 监听器未清理的问题，部署到生产环境前应至少升级到该版本。资料来源：[v1.4.1 release notes](https://github.com/punkpeye/pipenet/releases/tag/v1.4.1)
- **CLI 返回 `your url is: …` 后立即退出**：常见原因是使用了不兼容的旧版客户端或在子进程中未保活；建议改用 API 模式 `await pipenet({ port })` 并在主进程中保持引用。资料来源：[issue #1](https://github.com/punkpeye/pipenet/issues/1)
- **多域名解析失败**：自 v1.2.0 起服务端支持 `--domain` 多次传入，部署时需确保 DNS 已为每个域名配置通配 `A`/`CNAME` 指向服务端 IP。资料来源：[v1.2.0 release notes](https://github.com/punkpeye/pipenet/releases/tag/v1.2.0)

## See Also

- [README.md](https://github.com/punkpeye/pipenet/blob/main/README.md) — 完整 CLI 与 API 使用说明
- [src/server/index.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/index.ts) — 服务端模块导出清单
- [src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts) — 客户端长连接管理
- [package.json](https://github.com/punkpeye/pipenet/blob/main/package.json) — 脚本、依赖与 Node 版本约束

---

<a id='page-operations'></a>

## 运维、故障模式与生命周期事件

### 相关页面

相关主题：[客户端 API 与 CLI 使用](#page-client), [服务器部署与云端模式](#page-server)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/Tunnel.ts](https://github.com/punkpeye/pipenet/blob/main/src/Tunnel.ts)
- [src/TunnelCluster.ts](https://github.com/punkpeye/pipenet/blob/main/src/TunnelCluster.ts)
- [src/server/server.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/server.ts)
- [src/server/Client.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/Client.ts)
- [src/server/ClientManager.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/ClientManager.ts)
- [src/server/index.ts](https://github.com/punkpeye/pipenet/blob/main/src/server/index.ts)
- [src/pipenet.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.ts)
- [src/pipenet.spec.ts](https://github.com/punkpeye/pipenet/blob/main/src/pipenet.spec.ts)
- [README.md](https://github.com/punkpeye/pipenet/blob/main/README.md)
- [package.json](https://github.com/punkpeye/pipenet/blob/main/package.json)
</details>

# 运维、故障模式与生命周期事件

## 概述

pipenet 的核心职责是"将本地 HTTP 服务即时暴露到公网"，要稳定运行就必须妥善管理两类生命周期：**客户端隧道**（`Tunnel` → `TunnelCluster`）和**服务端代理**（`Client` → `ClientManager`）。本页聚焦于它们的启动、运行、关闭全过程，常见故障模式（4XX、监听器泄漏、隧道立即退出等）以及在云环境下的运维实践。

## 1. 客户端生命周期

### 1.1 启动阶段

`Tunnel` 构造函数默认 `host = 'https://pipenet.dev'`，并初始化 `closed = false` [src/Tunnel.ts]()。`open()` 内部调用 `_init`，向 `${host}/?new`（或 `${host}/${subdomain}`）发起 HTTP GET 请求 [src/Tunnel.ts]()。`pipenet()` 工厂函数接受 `port` 或 `OptionsWithPort`，并支持 Node 风格回调与 Promise 双 API [src/pipenet.ts]()。

成功获取 `ServerResponse` 后，`_establish` 创建 `TunnelCluster` 并以 `info.maxConn` 设置最大监听数；当首个底层 TCP 隧道打开时触发 `'url'` 事件 [src/Tunnel.ts]()。

### 1.2 状态机

```mermaid
stateDiagram-v2
    [*] --> Constructed: new Tunnel(opts)
    Constructed --> Resolving: open() -> _init()
    Resolving --> Established: 2xx + TCP open
    Resolving --> Retrying: 5xx/网络错误
    Resolving --> Aborted: 4xx (v1.4.2+)
    Retrying --> Resolving: 1s 后重试
    Established --> Closed: close()
    Aborted --> [*]
    Closed --> [*]
```

### 1.3 事件清单

| 事件 | 参数 | 含义 | 来源 |
|------|------|------|------|
| `url` | `string` | 首次公网 URL 就绪 | [src/Tunnel.ts]() |
| `request` | `{ method, path }` | 每个代理请求 | [README.md]() |
| `error` | `Error` | 隧道级错误 | [src/Tunnel.ts]() |
| `close` | — | 隧道已关闭 | [src/Tunnel.ts]() |

## 2. 服务端生命周期与钩子

### 2.1 客户端注册与离线检测

服务端 `Client` 在构造时启动 1 秒宽限 `graceTimeout`，并监听其 `TunnelAgent` 的 `online`/`offline` 事件：上线即清除定时器，下线则再次启动 1 秒计时后强制 `close()` [src/server/Client.ts]()。`ClientManager` 负责 `newClient` / `removeClient`，并根据冲突情况自动为重名 ID 重新分配随机子域 [src/server/ClientManager.spec.ts]()。

### 2.2 Hooks 钩子机制

v1.4.0 起服务端支持 `onRequest` 等钩子，可在 Koa 路由中获取 `{ method, path, tunnelId, headers, remoteAddress }` 上下文，常用于日志、限流与认证 [README.md](). 钩子通过 `ServerOptions` 传入，集成在 `router` 与 `TunnelAgent` 中。

### 2.3 共享隧道端口

针对 Docker / fly.io / Kubernetes 等只能暴露少数端口的环境，v1.3.0 引入 `TunnelServer`，由 `--tunnel-port` 启用，使所有客户端连接到同一端口 [README.md](). 服务端 `createServer` 在检测到 `opt.tunnelPort` 时构造 `TunnelServer` 并注入 `ClientManager` [src/server/server.ts]()。

## 3. 常见故障模式

### 3.1 4XX 导致的中止

`Tunnel._init` 区分 4XX 与 5XX：4XX 直接以服务端返回的 `message` 调用 `cb(new Error(...))`，不再重试 [src/Tunnel.ts](). v1.4.2 将此行为正式固化为"创建中止"（abort tunnel creation on 4XX），解决了 issue #1 中"`pipenet client` 偶发 404 但客户端仍处于半挂起状态"的问题。

### 3.2 监听器泄漏

v1.4.1 修复了"快速重连导致 `close` 监听器泄漏"问题：之前的 `Tunnel` 内部对 `tunnelCluster` 多次调用 `on('error', ...)` 累积监听器，触发 `MaxListenersExceededWarning`。修复后使用 `Map<Socket, handler>` 精确管理每次新 TCP 通道的处理器 [src/Tunnel.ts]().

### 3.3 网络中断与重试

当 `axios` 请求触发非 4XX 错误时，`_init` 走 `setTimeout(getUrl, 1000)` 循环重试 [src/Tunnel.ts]()。**注意**：该重试仅覆盖"获取隧道信息"阶段，已建立 TCP 隧道后的断线重连由 `TunnelCluster` 通过 `error` 事件透传，调用方应监听 `tunnel.on('error', ...)` 自行处理 [README.md]().

### 3.4 进程立即退出

issue #1 反馈"打印 `your url is: ...` 后立即返回命令行"。`pipenet` 客户端默认不会自动 `process.exit`，CLI 模式下应通过事件或 `tunnel.close()` 显式阻塞；集成方需保持事件循环活跃（如 `await` 一个永不 resolve 的 Promise 或保持 stdin 打开）。

## 4. 运维最佳实践

1. **始终监听 `error`/`close`**：服务端可能因 4XX 提前终止（v1.4.2），客户端可能因网络抖动断流。
2. **云部署使用 `--tunnel-port`**：与 `--port` 双端口同时暴露，避免每个客户端分配随机端口被防火墙拦截 [README.md]().
3. **使用 `onRequest` 钩子**集中记录访问日志与限流，避免在回调中散落处理。
4. **测试时显式 `close()`**：`createServer()` 与 `pipenet()` 返回的实例都实现了 `close`，`vitest` 用例中应在 `afterAll` 调用以释放端口 [src/pipenet.spec.ts]().
5. **构建产物**：`pnpm build` 通过 `tsc` 生成 `dist/`，`start:server` 直接运行 `dist/server/index.js` [package.json]().

## See Also

- 客户端 API 与配置参数
- 服务端 API 端点（`/api/status`, `/api/tunnels/:id/status`）
- Hooks 与多域名部署
- pipenet vs localtunnel vs zrok 对比

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：punkpeye/pipenet

摘要：发现 7 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：安装坑 - 来源证据：Gives 404。

## 1. 安装坑 · 来源证据：Gives 404

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Gives 404
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/punkpeye/pipenet/issues/1 | 来源讨论提到 npm 相关条件，需在安装/试用前复核。

## 2. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/punkpeye/pipenet | README/documentation is current enough for a first validation pass.

## 3. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/punkpeye/pipenet | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/punkpeye/pipenet | no_demo; severity=medium

## 5. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/punkpeye/pipenet | no_demo; severity=medium

## 6. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/punkpeye/pipenet | issue_or_pr_quality=unknown

## 7. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/punkpeye/pipenet | release_recency=unknown

<!-- canonical_name: punkpeye/pipenet; human_manual_source: deepwiki_human_wiki -->
