# @authhero/proxy 中文文档

规范地址：https://npmcn.com/package/%40authhero/proxy/

版本：0\.11\.13
npm 元数据更新时间：2026-11-05T14:42:16.535Z
中文译文更新时间：2026-11-08T03:23:51.119Z
软件包许可：AGPL-3\.0-only

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40authhero/proxy
原文对照：https://npmcn.com/package/%40authhero/proxy/?lang=original
项目主页：https://authhero.net/
源码仓库：https://github.com/sesamyab/authhero

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：473 kB，41 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：hono ^4\.6\.8，@hono/zod-openapi ^1\.4\.0
- 首次发布：2026-05-27T10:41:05.040Z
- 最新版本发布：2026-11-05T14:42:15.975Z
- 近 30 天下载量：1912（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：63（近 12 个月 63 个）

## 中文简介

多租户 HTTP 逆向代理库 [浩诺](https://hono.dev/)解决收到的请求 `Host` 给租户的页眉, 匹配 JSON 配置的路由列表( path / method / hosters / headers / 查询) , 并运行每个匹配的路由 treou

## 安装

```sh
npm install @authhero/proxy
```

也可以使用：`pnpm add @authhero/proxy`、`yarn add @authhero/proxy`、`bun add @authhero/proxy`

## README

# @authhero/ 代理服务器

多租户 HTTP 逆向代理库 [浩诺](https://hono.dev/)解决收到的请求 `Host` 头到租户,与JSON配置的路由列表相匹配(路径/方法/主机/头头/查询),并通过命令的处理器链来运行每个匹配路由——中间软件风格的转换,然后是产生响应的终端处理器.

设计运行于Cloudflare Workers,Node.js, Bun,或任何Hono相容的运行时间. 这个软件包仅是数据平面 – 代理路由 CRUD lives in the `authhero` 核心资源(`/api/v2/proxy-routes`),而基础计划由每个数据库适配器运出(`@authhero/kysely-adapter`, (中文(简体) ), `@authhero/drizzle`, (中文(简体) ), `@authhero/aws-adapter`) (中文(简体) ).

## 安装

```bash
pnpm add @authhero/proxy hono @hono/zod-openapi
```

`hono` 财务报告和审定财务报表 `@hono/zod-openapi` 是同伴的依赖关系.

## 概念

A 类 **路径** 有两个部分:

-   `match` —— 说 `{ hosts?, methods?, path, headers?, query? }`。路径使用Hono的模式语法(`/api/*`, (中文(简体) ), `/users/:id`) (中文(简体) ). `hosts` 接受准确或 `*.example.com` 通通证. `headers` 财务报告和审定财务报表 `query` 名称 \\ regex.
-   `handlers` ——命令的处理器配置阵列. 每个操作员是 `{ type, options }`编辑 **最后一个** 处理器是终端(它产生响应); 早期的处理器像Hono中间软件(`(c, next) => …`) (中文(简体) ).

内置处理器 :

| 类型 | 作用 | 它会做什么 |
| --- | --- | --- |
| `cors` | 中间软件 | 对选择方案预先飞行的答复;在答复中增加CORS标题. |
| `basic_auth` | 中间软件 | 需要在 `Authorization: Basic` 头曰. |
| `headers` | 中间软件 | 添加/删除请求和回复标题. |
| `cache` | 中间软件 | 喷出 `Cache-Control: public, max-age=N` 如果还没有设置. |
| `forwarded_headers` | 中间软件 | 设定 `X-Forwarded-For`, (中文(简体) ), `X-Forwarded-Host`, (中文(简体) ), `X-Forwarded-Proto`, (中文(简体) ), `X-Real-IP`, (中文(简体) ), `X-Original-URL` 从CF-Concting-IP。 自动准备到任何遗漏的链条. |
| `rewrite_cookies` | 中间软件 | 重写上游 `Set-Cookie: …; Domain=` 到请求主机. |
| `rewrite_location` | 中间软件 | 重写 `Location` 关于3xxx从上游来源对请求来源的答复的标题. |
| `http` | 终端 | 转发到上游的 HTTP 通过 `fetch`。 。 。 . |
| `service_binding` | 终端 | 转发到 Cloudflare 服务绑定(`env.MY_API.fetch`) (中文(简体) ). |
| `dispatch_namespace` | 终端 | 向云旗工人派出平台命名空间(`env.DISPATCHER.get(scriptName).fetch`) (中文(简体) ). `script_name` 接受 `{tenant_id}`, (中文(简体) ), `{custom_domain_id}`, (中文(简体) ), `{domain}`, (中文(简体) ), `{host}` 占位符 . |
| `redirect` | 终端 | 返回 a 301/302/307/308重新定向. |
| `static` | 终端 | 返回一个静态身体(健康检查效果良好). |

### 客户端 IP 转发

`forwarded_headers` 保证:代理机将它预先加到每个路由链上(和 `defaultHandlers`),这还没有宣布,所以存储在KV或控制平面中的路由表不能默默地放下访客IP. 处理器列表中任何位置的链条都完全按照配置.

处理器忽略一个 `CF-Connecting-IP` 属于Cloudflare自己的出版范围——当代理到达工人与工人之间时,信头会随身携带,盖上它就可以覆盖真正的客户端IP,一个已经录入的更早的跳出 `X-Forwarded-For`。在这种情况下,入境链保持不变;入境 `X-Real-IP` 永远不会被信任为一个倒置的背面,因为它是可客户端的。 选择退出 `{ type: "forwarded_headers", options: { skip_cloudflare_client_ip: false } }`。 。 。 .

通过 a 注册自定义处理器 `HandlerRegistry`。 。 。 .

## 快速启动( 静态配置)

```ts
import { createProxyApp, createStaticProxyAdapter, httpRoute } from "@authhero/proxy";

const data = createStaticProxyAdapter({
  hosts: {
    "acme.example.com": {
      tenant_id: "acme",
      routes: [
        httpRoute("https://acme.vercel.app"),                     // sugar for { match: {path:"/*"}, handlers: [{type:"http",...}] }
        {
          match: { path: "/healthz" },
          handlers: [
            { type: "static", options: { status: 200, json: { ok: true } } },
          ],
        },
        {
          match: { path: "/api/*" },
          handlers: [
            { type: "cors", options: { origins: ["https://app.example.com"] } },
            { type: "http", options: { upstream_url: "https://api.acme.vercel.app" } },
          ],
        },
      ],
    },
  },
});

const app = createProxyApp({ data });
export default app;
```

## Cloudflare 服务绑定

向服务机构(如内部API工人)发送信息,在工人登记簿上声明,并传递给 `createProxyApp`数字 :

```ts
export default {
  fetch(req: Request, env: Env, ctx: ExecutionContext) {
    const app = createProxyApp({
      data: ...,
      bindings: { API2: env.API2 },
    });
    return app.fetch(req);
  },
};
```

然后一个路线可以使用:

```ts
{ match: { hosts: ["api.example.com"] }, handlers: [
    { type: "forwarded_headers", options: {} },
    { type: "service_binding", options: { binding: "API2" } },
] }
```

## 向工人派遣平台

前往Cloudflare发送点名空间的普通工人的路线 脚本名称支持根据请求从已解决的主机替换的占位符 :

```toml
# wrangler.toml
[[dispatch_namespaces]]
binding = "DISPATCHER"
namespace = "authhero-tenants"
```

```ts
// One catch-all route per host dispatches to that tenant's worker.
{ match: { path: "/*" }, handlers: [
    { type: "dispatch_namespace", options: {
        binding: "DISPATCHER",
        script_name: "tenant-{tenant_id}-auth",  // e.g. "tenant-acme-auth"
        // Optional: cpu_ms, subrequests — forwarded to dispatcher.get(...)
    }},
] }
```

可用的占位符 : `{tenant_id}`, (中文(简体) ), `{custom_domain_id}`, (中文(简体) ), `{domain}`, (中文(简体) ), `{host}`。前三个来自已解决的东道主记录; `{host}` 是请求 `Host` 头曰.

## 取代由上游来源的饼干和再定向

遗产 Sesamy 代理重写 `Set-Cookie: Domain=upstream.example.com` 和 3xx 数据 `Location: https://upstream.example.com/…` 信头因此指向公共自定义域. 等同于v2::

```ts
{
  match: { path: "/*" },
  handlers: [
    { type: "forwarded_headers", options: {} },
    { type: "rewrite_cookies", options: {} },   // infers upstream host from the http/service_binding handler
    { type: "rewrite_location", options: {} },  // ditto
    { type: "http", options: { upstream_url: "https://upstream.example.com" } },
  ],
}
```

(你可以针) `upstream_host` 编号 : `upstream_origin` 很明显,如果你不想自动推论。 )

## 动态路线(数据库支持)

生产时,将路线储存在数据库中并按要求解决. AuthHero 适配器包装船 a `createProxyDataAdapter(db)` 返回满分的助手 `ProxyDataAdapter` (中文(简体) ) `resolveHost`与他们的计划接通:

```ts
import { Kysely } from "kysely";
import { createProxyApp } from "@authhero/proxy";
import { createProxyDataAdapter } from "@authhero/kysely-adapter";

const db = new Kysely({ /* dialect */ });

const app = createProxyApp({
  data: createProxyDataAdapter(db),
});
```

这个 `proxy_routes` 表格带有标准的 AuthHero 迁移——通过 `migrateToLatest(db)` (或等同的细雨/锯子阶)已足.

## 遥控平面( HTTP 适配器)

如果代理运行与AuthHero控制平面(不同的工人,不同的VPC,不同的区域)分开,则使用 `createHttpProxyAdapter` 以读取 HTTP 上的路由配置 :

```ts
import {
  createProxyApp,
  createHttpProxyAdapter,
  createCacheAdapterHostCache,
  createInMemoryHostCache,
} from "@authhero/proxy";
import { createCloudflareCache } from "@authhero/cloudflare-adapter";

const httpAdapter = createHttpProxyAdapter({
  baseUrl: "https://auth.example.com",
  clientId: env.PROXY_CLIENT_ID,
  clientSecret: env.PROXY_CLIENT_SECRET,
});

// Three-tier cache: in-memory (per-isolate) → Cloudflare Cache API (per-colo) → control plane.
const inMemory = createInMemoryHostCache(httpAdapter, { freshTtlMs: 60_000, staleTtlMs: 600_000 });
const resolver = createCacheAdapterHostCache({
  upstream: inMemory,
  cache: createCloudflareCache({ cacheName: "authhero-proxy-hosts" }),
  freshTtlMs: 60 * 60_000,           // 1 hour fresh
  staleTtlMs: 23 * 60 * 60_000,      // SWR for 23 more hours (24h total)
  waitUntil: (p) => ctx.waitUntil(p),
});

const app = createProxyApp({
  data: httpAdapter,
  resolver,                                  // share across requests
  bindings: { API2: env.API2 },
});
```

HTTP 适配器交换 `client_id` + 键 `client_secret` 用于在 `${baseUrl}/oauth/token`,然后打电话 `GET ${baseUrl}/api/v2/proxy/control-plane/hosts/:host`. 控制平面必须使用系统范围证书(与租户代币分开)来暴露这一端点.

## 控制平面端点(服务器侧)

在您的 AuthHero 服务器中,选择通过线接解析器并指向 JWKS, 标志控制飞机无记名标志。 认证在 认证持证人JWT(RS/ES algs, `iss === env.ISSUER`范围 `proxy:resolve_host`:

```ts
import { init } from "authhero";
import { createProxyDataAdapter } from "@authhero/kysely-adapter";

const proxyData = createProxyDataAdapter(db);

const { app } = init({
  dataAdapter,
  proxyControlPlane: {
    resolveHost: proxyData.resolveHost,
    jwksUrl: `${env.ISSUER}/.well-known/jwks.json`,
    // On Workers, route through a service binding to keep the request
    // off the public network:
    // jwksFetch: (url) => env.JWKS_SERVICE.fetch(url),
  },
});
```

## KV 出版的读取复制品( 在光亮的 HTTP 适配器上推荐)

HTTP 适配器通过双跳认证调用读取路由(token mint +) 解决),每一次缓存出错。 为了把跳跃从热道上移出,有 控制平面 **发布** 每个解析出的主机块到 Cloudflare KV 命名空间, 并拥有代理 **读取** 与一个单一的, 未经认证 `KV.get`编辑 control-plane DB 保留了真理的来源;KV是已出版的已读复制品.

**代理侧** —— 说 `createKvProxyAdapter`,将HTTP适配器保留为 迁移中错失/误差倒计时 :

```ts
import {
  createProxyApp,
  createKvProxyAdapter,
  createHttpProxyAdapter,
  createCacheAdapterHostCache,
  createInMemoryHostCache,
  type ProxyDataAdapter,
} from "@authhero/proxy";
import { createCloudflareCache } from "@authhero/cloudflare-adapter";

const kv = createKvProxyAdapter({ kv: env.PROXY_HOSTS, timeoutMs: 1000 });
const http = createHttpProxyAdapter({ baseUrl, clientId, clientSecret });

const upstream: ProxyDataAdapter = {
  proxyRoutes: kv.proxyRoutes, // read-only
  async resolveHost(host) {
    try {
      const hit = await kv.resolveHost(host);
      if (hit) return hit;
    } catch {
      /* KV slow/unavailable — fall through */
    }
    return http.resolveHost(host); // miss / error fallback
  },
};

const resolver = createCacheAdapterHostCache({
  upstream: createInMemoryHostCache(upstream, { freshTtlMs: 60_000 }),
  cache: createCloudflareCache({ cacheName: "authhero-proxy-hosts" }),
  freshTtlMs: 60 * 60_000,
  negativeTtlMs: 60_000,
  waitUntil: (p) => ctx.waitUntil(p),
});

createProxyApp({ data: upstream, resolver });
```

**控制平面** ——将适配器打包一次 `wrapProxyAdaptersWithKvPublish` (从) `authhero`将包裹的一对传给 管理API 和 `createApplySyncEvents`,然后种子现有主机 与 `backfillProxyHostsToKv`。 KV 命名空间必须生活在 **不变 云浮账户** 作为代理工人。 全文见出版物 \* 种子 \* 使用指南 文档中: [代理 ~ 形状 3b](https://www.authhero.net/customization/proxy/#shape-3b-%E2%80%94-split-db-kv-published-read-replica-recommended-over-plain-shape-3)。 。 。 .

## 主机缓存

`resolveHost` 每一个请求都要求。 用内置的 stale- while- revalidate 缓存包起来 :

```ts
const app = createProxyApp({
  data,
  cache: {
    freshTtlMs: 5 * 60_000,
    staleTtlMs: 60 * 60_000,
    negativeTtlMs: 30_000,
    waitUntil: (p) => ctx.waitUntil(p),
  },
});
```

云花岗工人,线条 `ExecutionContext.waitUntil` 与 `AsyncLocalStorage` 所以背景更新 幸存的反应.

## 自定义处理器

定义您的处理器类型 :

```ts
import { z } from "@hono/zod-openapi";
import { HandlerRegistry, defineHandler, registerBuiltinHandlers, createProxyApp } from "@authhero/proxy";

const myHandler = defineHandler<{ secret: string }>({
  type: "hmac_verify",
  optionsSchema: z.object({ secret: z.string() }),
  build(options) {
    return async (c, next) => {
      const sig = c.req.header("x-signature");
      if (!sig || !await verify(sig, options.secret, c.req.raw)) {
        return new Response("Bad signature", { status: 401 });
      }
      await next();
    };
  },
});

const registry = new HandlerRegistry();
registerBuiltinHandlers(registry);
registry.add(myHandler);

const app = createProxyApp({ data, registry });
```

## 路线计划( Zod)

所有计划作为Zod计划再出口(`proxyRouteSchema`, (中文(简体) ), `matchSchema`, (中文(简体) ), `handlerConfigSchema`用于在您自己的管理 UI 中验证.

## 出口

-   `createProxyApp(options)` - 主Hono应用工厂
-   `createProxyDataPlaneRouter` 编号 : `createProxyDataPlaneHandler` - 数据平面管道
-   `createStaticProxyAdapter` 编号 : `httpRoute` ——静态配置助手
-   `createHttpProxyAdapter` - HTTP控制平面适配器
-   `createInMemoryHostCache` 编号 : `createCacheAdapterHostCache` ——缓存层(`createCacheApiHostCache` 也可以导出但为适应器包装而贬值)
-   `HandlerRegistry` 编号 : `defineHandler` 编号 : `registerBuiltinHandlers` + 每个内置处理器
-   `compileHostApp`, (中文(简体) ), `sortRoutes`, (中文(简体) ), `matchesHost`, (中文(简体) ), `matchesAnyHost`, (中文(简体) ), `buildMatchFilter`

数据库支持的适配器生活在 AuthHero 适配器包中: `@authhero/kysely-adapter`, (中文(简体) ), `@authhero/drizzle`, (中文(简体) ), `@authhero/aws-adapter`。 。 。 .

## 许可证

麻省理工学院

## 常见问题

### @authhero/proxy 是什么？

多租户 HTTP 逆向代理库 浩诺解决收到的请求 Host 给租户的页眉, 匹配 JSON 配置的路由列表\( path / method / hosters / headers / 查询\) , 并运行每个匹配的路由 treou

### 如何安装 @authhero/proxy？

在项目目录运行 npm install @authhero/proxy，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：hono（^4\.6\.8）、@hono/zod-openapi（^1\.4\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @authhero/proxy 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @authhero/proxy 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @authhero/proxy 可以商用吗？

@authhero/proxy 使用 AGPL-3\.0-only 许可。最严格的 Copyleft：除分发外，通过网络向用户提供基于它的服务也需要开源对应源码。闭源 SaaS 使用前务必评估。以上为概括，不构成法律意见，请以许可原文为准。

### @authhero/proxy 的下载量有多少？

根据 npm 官方下载统计，@authhero/proxy 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,912 次，日均约 64 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @authhero/proxy 还在维护吗？

最新版本 0\.11\.13 发布于 2026/11/05（2 天前）；至今共发布 63 个版本，其中过去 12 个月发布了 63 个；首次发布于 2026/05/27。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

