Skip to content

4.3 Public API 链路

学习目标

完成本节后,你将能够:

  1. 解释 Public API 和 tRPC 在鉴权、稳定性和文档上的差异。
  2. 读懂 withMiddlewarescreateAuthedProjectAPIRoute 的分工。
  3. 知道公共 API 变更为什么要同步 Zod schema、Fern 和 generated client。

4.3.1 先给结论

Public API 是外部 contract,不是给 UI 用的内部 convenience route。

它的标准链路是:

text
pages/api/public route -> withMiddlewares -> createAuthedProjectAPIRoute -> service/repository -> schema response

这条链路负责:

  • CORS 和 HTTP method dispatch;
  • 统一错误边界;
  • API key / admin API key auth;
  • project scope 和 access level;
  • rate limit;
  • Zod query/body/response;
  • OpenTelemetry context;
  • dev 环境 response validation;
  • 对外 API contract 和 Fern 同步。

4.3.2 链路图

4.3.3 withMiddlewares:HTTP 边界

源码:web/src/features/public-api/server/withMiddlewares.ts

它负责每个 Public API route 的外层 HTTP 行为:

行为作用
runMiddleware(req, res, cors)统一 CORS。
method dispatch只允许 route 声明的 GET/POST/PUT/DELETE/PATCH。
contextWithLangfuseProps设置 ClickHouse surface = publicapi,route 来自 request。
ClickHouseResourceError handling返回 422 和用户可理解的资源限制提示。
BaseError/Zod/Prisma handling统一 public JSON error shape。
unstable error contract特定 API surface 可使用不同错误契约。

withMiddlewares 是 HTTP 层错误和 method 的外壳,不应该承载业务逻辑。

4.3.4 createAuthedProjectAPIRoute:项目级 API contract

源码:web/src/features/public-api/server/createAuthedProjectAPIRoute.ts

它把一条 project-scoped Public API route 描述成配置:

配置项含义
name日志和调试用 route 名。
querySchemaZod query parser。
bodySchemaZod body parser。
responseSchemaZod response schema,dev 环境会校验。
successStatusCode默认 200,可覆盖。
rateLimitResource使用哪类 rate limit bucket。
rateLimitUpgradePathrate limited 时给用户的升级路径。
isAdminApiKeyAuthAllowedself-hosted 下是否允许 admin API key。
allowedAccessLevels接受 project key、scores key 等哪些 access level。
allowInAppAgentKey是否允许 in-app agent key 调用。
rejectInEventsOnlyModev4 events_only 时拒绝读 legacy 表的 endpoint。
fn真正业务 handler。

这个 wrapper 的价值是把“每个 Public API 都必须遵守的边界”统一起来,避免每条 route 自己实现 auth、rate limit 和 schema。

4.3.5 鉴权方式

Public API 不使用 UI session,而是从 Authorization header 验证 API key。

方式行为
regular API keyApiAuthService.verifyAuthHeaderAndReturnScope 返回 project scope、access level、plan、rate limit overrides。
Bearer public key可用于某些 scores access level endpoint。
admin API key仅 self-hosted,要求 Bearer token、x-langfuse-admin-api-keyx-langfuse-project-id

鉴权结果会变成:

text
auth.scope.projectId
auth.scope.accessLevel
auth.scope.orgId
auth.scope.apiKeyId
auth.scope.publicKey

后续 handler 不应该重新从 request 自己猜 project scope。

4.3.6 tRPC vs Public API

维度tRPCPublic API
使用者Web UISDK、外部用户、自动化脚本
鉴权NextAuth session + project/org membershipAPI key scope + access level + rate limit
稳定性内部 contract,可随 UI 演进外部 contract,变更要兼容
校验procedure input schemaquery/body/response schema
错误格式tRPC errorpublic JSON error contract
文档不需要 Fern需要 Fern/API docs/SDK 同步
版本和迁移UI 同步部署可能被旧 SDK 和客户脚本长期调用

所以新增外部 endpoint 时,不要复用 tRPC router 作为 Public API。它们面向的 contract 不同。

4.3.7 Public API 变更的同步面

改动同步位置
新增 routeweb/src/pages/api/public/**、wrapper、tests。
新增 query/body fieldZod schema、Fern schema、API docs。
新增 response fieldresponseSchema、Fern response、generated clients。
改错误语义withMiddlewares 或 route-specific error contract。
改 pagination/filterPublic API types、query builder、规模保护。
改 legacy/v4 数据源rejectInEventsOnlyMode、query path、migration docs。

Public API 是外部承诺。即使代码能编译,contract 没同步也算未完成。

4.3.8 自检清单

  • route 是否包在 withMiddlewares 里?
  • project-scoped route 是否使用 createAuthedProjectAPIRoute
  • query/body/response 是否都有 Zod schema?
  • handler 是否使用 auth.scope.projectId
  • 是否设置了正确的 allowedAccessLevelsrateLimitResource
  • response 是否可能过大,是否需要 field selection 或 pagination?
  • 是否读 legacy traces/observations,在 events_only 模式下是否要拒绝?
  • Fern 和 generated client 是否需要同步?

下一节

Ingestion 链路