Files
claude-api-proxy/_bmad-output/implementation-artifacts/tech-spec-claude-api-proxy.md
D8D Developer fafef0e034 feat: 实现 Claude API 透传代理服务
实现完整的 Claude API 代理服务,支持:
- 透传 /v1/* 路径到上游 API
- 流式 (SSE) 和非流式响应
- JSONL 格式请求日志
- /health 健康检查端点
- Docker 多阶段构建
- Gitea Actions CI/CD 工作流

安全加固:
- 容器以非 root 用户运行
- 添加 Docker HEALTHCHECK
- 实现优雅关闭处理 (SIGTERM/SIGINT)

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-03-20 06:47:46 +00:00

8.9 KiB
Raw Blame History

title, slug, created, status, stepsCompleted, tech_stack, files_to_modify, code_patterns, test_patterns
title slug created status stepsCompleted tech_stack files_to_modify code_patterns test_patterns
Claude API 透传代理服务 claude-api-proxy 2026-03-20T04:30:00.000Z completed
1
2
3
4
5
6
Node.js
Express
TypeScript
axios
Docker
package.json
tsconfig.json
src/index.ts
src/proxy.ts
src/health.ts
src/logger.ts
.env.example
Dockerfile
.dockerignore
.gitea/workflows/release.yaml
流式响应: axios stream + pipe
错误处理: axios error + 统一 JSON 格式
日志: JSONL 格式存储到 /tmp/proxy.jsonl
Docker: 多阶段构建 + 生产依赖分离
CI/CD: Gitea Actions + 阿里云镜像仓库

Tech-Spec: Claude API 透传代理服务

Created: 2026-03-20T04:30:00.000Z

Overview

Problem Statement

D8D 项目有一个 API Key 池,目前直接请求 Claude 官方 API。但官方 API 有 IP 并发限制,单个 IP 的并发数有限。为了绕过这个限制,需要启动多个代理容器实例,每个实例有不同的出口 IP从而分散请求。

Solution

创建一个纯透传的 Claude API 代理服务:

  • 使用 Express.js 构建轻量级代理服务
  • 接收什么就转发什么,不做任何业务逻辑处理
  • 支持流式streaming和非流式两种输出模式
  • 构建为 Docker 镜像,部署到阿里云 ECI (t5-lc2m1.nano: 0.5 CPU, 1G 内存)
  • 通过 K8S 管理 Pod 和 Ingress 配置

Scope

In Scope:

  • Express.js 代理服务(透传 /v1/messages 端点)
  • 支持流式和非流式响应
  • Dockerfile 构建配置
  • Gitea workflow 自动构建镜像
  • K8S 部署配置参考

Out of Scope:

  • 用户认证和授权
  • 余额检查和计费
  • API Key 池管理(由 D8D 主项目处理)
  • 复杂的日志和监控

Context for Development

Codebase Patterns

参考项目:/mnt/code-fast/d8d-worktrees/merge-epics

代理转发参考:

  • src/server/api/ai/claude/v1/messages/post.ts - Claude API 调用实现
  • 使用 axios 进行 HTTP 请求
  • 流式响应使用 TransformStream 处理

K8S 部署参考:

  • src/server/utils/k8s.ts - K8S 客户端封装
  • 使用阿里云 ECI (virtual-kubelet)
  • 创建 Deployment、Service、Ingress

Docker 构建参考:

  • Dockerfile - 多阶段构建
  • .gitea/workflows/release.yaml - Gitea Actions 构建流程

Files to Reference

File Purpose
/mnt/code-fast/d8d-worktrees/merge-epics/src/server/api/ai/claude/v1/messages/post.ts Claude API 转发逻辑参考
/mnt/code-fast/d8d-worktrees/merge-epics/src/server/utils/k8s.ts K8S 客户端实现参考
/mnt/code-fast/d8d-worktrees/merge-epics/Dockerfile Docker 构建参考
/mnt/code-fast/d8d-worktrees/merge-epics/.gitea/workflows/release.yaml Gitea workflow 参考

Technical Decisions

  • 框架选择: Express.js用户指定轻量简单
  • 语言: TypeScript类型安全
  • HTTP 客户端: axios支持流式响应
  • 容器规格: 阿里云 ECI t5-lc2m1.nano (0.5 CPU, 1G 内存)
  • 镜像仓库: registry.cn-beijing.aliyuncs.com/d8dcloud/
  • 端口: 3000
  • API URL: 环境变量 ANTHROPIC_BASE_URL,本地读取 .env,容器通过 K8S 注入
  • 智谱端点: https://open.bigmodel.cn/api/anthropic
  • 路径透传: 完全透传 /v1/* 路径到上游 API
  • 健康检查: 添加 /health 端点供 K8S 探针使用
  • Headers 透传: x-api-keyauthorizationanthropic-versioncontent-typeaccept
  • 超时设置: 不设置 axios timeout让上游 API 自己处理
  • 日志格式: JSONL 格式存储到 /tmp/proxy.jsonl,容器重启自动清理
  • 日志内容: 只记录元信息time, method, path, status, duration, stream, error不记录请求/响应 body
  • 请求体大小: Express body-parser 设置 limit: '50mb'
  • 包管理器: pnpm与参考项目一致
  • 镜像名称: registry.cn-beijing.aliyuncs.com/d8dcloud/claude-api-proxy:${VERSION}
  • HTTPS: 依赖 K8S Ingress 处理 TLS代理本身不需要 HTTPS
  • 流式错误处理: 流式传输中若上游报错,关闭客户端连接,记录错误日志
  • 启动命令: node dist/index.js

Implementation Plan

Tasks

Task 1: 项目初始化

  • 创建 package.json 配置 Express、axios、TypeScript 依赖
  • 创建 tsconfig.json 配置 TypeScript 编译选项
  • 创建 .env.example 环境变量示例

Task 2: 核心代理服务

  • 创建 src/index.ts Express 入口,监听端口 3000
  • 创建 src/proxy.ts 代理逻辑:
    • 捕获所有 /v1/* 路由
    • 透传 headers (x-api-key, authorization, anthropic-version, content-type, accept)
    • 透传 body 到 ANTHROPIC_BASE_URL
    • 流式响应:设置 SSE headers使用 axios stream + pipe
    • 非流式响应:直接转发 JSON
    • 不设置 axios timeout,让上游 API 自己处理
    • 监听 req.on('close') 处理客户端断开
    • 流式错误处理:上游流式报错时关闭客户端连接,记录日志
  • 设置 Express body-parser limit: '50mb'

Task 3: 日志服务

  • 创建 src/logger.ts 日志工具
  • JSONL 格式写入 /tmp/proxy.jsonl
  • 记录字段time, method, path, status, duration, stream?, error?
  • 不记录请求/响应 body(避免敏感数据泄露)

Task 4: 健康检查

  • 创建 src/health.ts 添加 /health 端点
  • 返回 { status: 'ok', timestamp: ISO时间 }

Task 5: Docker 构建配置

  • 创建 Dockerfile 多阶段构建
  • 构建阶段pnpm 安装依赖 + TypeScript 编译
  • 运行阶段:只包含生产依赖 + 编译产物
  • 暴露端口 3000
  • 启动命令:CMD ["node", "dist/index.js"]
  • 创建 .dockerignore 排除 node_modules、.git、.env 等

Task 6: CI/CD 工作流

  • 创建 .gitea/workflows/release.yaml
  • 触发条件push 到 release/* 分支
  • 步骤:提取版本号 → 登录阿里云镜像仓库 → 构建推送镜像
  • 镜像名称:registry.cn-beijing.aliyuncs.com/d8dcloud/claude-api-proxy:${VERSION}

Acceptance Criteria

AC1: 非流式请求转发

  • Given: 客户端发送 POST /v1/messages 请求 (stream: false)
  • When: 代理收到请求
  • Then: 请求被转发到 ANTHROPIC_BASE_URL/v1/messages,响应完整返回

AC2: 流式请求转发

  • Given: 客户端发送 POST /v1/messages 请求 (stream: true)
  • When: 代理收到请求
  • Then: 设置 SSE headers流式转发响应数据
  • And: 若流式过程中上游报错,关闭客户端连接并记录日志

AC3: 健康检查

  • Given: 客户端请求 GET /health
  • When: 代理收到请求
  • Then: 返回 { status: 'ok', timestamp: '...' } 状态码 200

AC4: Docker 镜像构建

  • Given: 执行 docker build
  • When: 构建完成
  • Then: 镜像大小 < 200MB能正常启动并监听 3000 端口

AC5: Headers 透传

  • Given: 请求包含 x-api-keyauthorizationanthropic-version headers
  • When: 代理转发请求
  • Then: 这些 headers 被完整传递到上游 API

AC6: 错误透传

  • Given: 上游 API 返回错误响应(如 400/401/429/500
  • When: 代理收到错误响应
  • Then: 透传错误状态码和响应 body 给客户端

Additional Context

Dependencies

生产依赖:

  • express - Web 框架
  • axios - HTTP 客户端(支持流式)
  • dotenv - 环境变量加载

开发依赖:

  • typescript - TypeScript 编译器
  • @types/express - Express 类型定义
  • @types/node - Node.js 类型定义
  • tsx - TypeScript 执行器(支持热重载)
  • tsc-alias - TypeScript 路径别名处理

Testing Strategy

  • 手动测试流式和非流式响应
  • 使用 curl 测试代理功能

Notes

  • 代理服务需要完全透传,包括 headers 和 body
  • 流式响应需要正确处理 SSE (Server-Sent Events) 格式
  • API Key 通过请求头 x-api-key 或 Authorization 传递
  • 超时策略:不设置 axios timeoutAI 请求可能耗时很长
  • 日志清理:存储在 /tmp 目录,容器重启自动清空,不会累积
  • 安全考虑:日志不记录请求/响应 body避免敏感数据泄露
  • HTTPS/TLS:代理本身不处理 HTTPS完全依赖 K8S Ingress 处理 TLS
  • 流式错误处理:流式传输中上游报错时,直接关闭客户端连接
  • 镜像命名registry.cn-beijing.aliyuncs.com/d8dcloud/claude-api-proxy:${VERSION}

Review Notes

  • 对抗性审查已完成 (2026-03-20)
  • 发现总数: 12 个 (2 严重, 4 高, 4 中, 2 低)
  • 修复数量: 3 个 (F1, F3, F4)
  • 跳过数量: 9 个 (经专家讨论确认合理)
  • 解决方案: 派对模式专家讨论 (Winston, Amelia, Barry, Quinn)

已修复:

  • F1: Docker 添加 USER node 和 HEALTHCHECK
  • F3: 添加 SIGTERM/SIGINT 优雅关闭处理
  • F4: 流式错误处理添加 writableEnded 检查

已跳过 (合理原因):

  • F2: 同步日志对轻量代理可接受
  • F5: 透传代理不应验证请求体
  • F6-F12: 低影响或过度优化