feat(Sora): 直连生成并移除sora2api依赖

实现直连 Sora 客户端、媒体落地与清理策略\n更新网关与前端配置以支持 Sora 平台\n补齐单元测试与契约测试,新增 curl 测试脚本\n\n测试: go test ./... -tags=unit
This commit is contained in:
yangjianbo
2026-02-01 21:37:10 +08:00
parent 78d0ca3775
commit 399dd78b2a
39 changed files with 3120 additions and 1189 deletions

111
deploy/Dockerfile Normal file
View File

@@ -0,0 +1,111 @@
# =============================================================================
# Sub2API Multi-Stage Dockerfile
# =============================================================================
# Stage 1: Build frontend
# Stage 2: Build Go backend with embedded frontend
# Stage 3: Final minimal image
# =============================================================================
ARG NODE_IMAGE=node:24-alpine
ARG GOLANG_IMAGE=golang:1.25.5-alpine
ARG ALPINE_IMAGE=alpine:3.20
ARG GOPROXY=https://goproxy.cn,direct
ARG GOSUMDB=sum.golang.google.cn
# -----------------------------------------------------------------------------
# Stage 1: Frontend Builder
# -----------------------------------------------------------------------------
FROM ${NODE_IMAGE} AS frontend-builder
WORKDIR /app/frontend
# Install pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# Install dependencies first (better caching)
COPY frontend/package.json frontend/pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
# Copy frontend source and build
COPY frontend/ ./
RUN pnpm run build
# -----------------------------------------------------------------------------
# Stage 2: Backend Builder
# -----------------------------------------------------------------------------
FROM ${GOLANG_IMAGE} AS backend-builder
# Build arguments for version info (set by CI)
ARG VERSION=docker
ARG COMMIT=docker
ARG DATE
ARG GOPROXY
ARG GOSUMDB
ENV GOPROXY=${GOPROXY}
ENV GOSUMDB=${GOSUMDB}
# Install build dependencies
RUN apk add --no-cache git ca-certificates tzdata
WORKDIR /app/backend
# Copy go mod files first (better caching)
COPY backend/go.mod backend/go.sum ./
RUN go mod download
# Copy backend source first
COPY backend/ ./
# Copy frontend dist from previous stage (must be after backend copy to avoid being overwritten)
COPY --from=frontend-builder /app/backend/internal/web/dist ./internal/web/dist
# Build the binary (BuildType=release for CI builds, embed frontend)
RUN CGO_ENABLED=0 GOOS=linux go build \
-tags embed \
-ldflags="-s -w -X main.Commit=${COMMIT} -X main.Date=${DATE:-$(date -u +%Y-%m-%dT%H:%M:%SZ)} -X main.BuildType=release" \
-o /app/sub2api \
./cmd/server
# -----------------------------------------------------------------------------
# Stage 3: Final Runtime Image
# -----------------------------------------------------------------------------
FROM ${ALPINE_IMAGE}
# Labels
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>"
LABEL description="Sub2API - AI API Gateway Platform"
LABEL org.opencontainers.image.source="https://github.com/Wei-Shaw/sub2api"
# Install runtime dependencies
RUN apk add --no-cache \
ca-certificates \
tzdata \
curl \
&& rm -rf /var/cache/apk/*
# Create non-root user
RUN addgroup -g 1000 sub2api && \
adduser -u 1000 -G sub2api -s /bin/sh -D sub2api
# Set working directory
WORKDIR /app
# Copy binary from builder
COPY --from=backend-builder /app/sub2api /app/sub2api
# Create data directory
RUN mkdir -p /app/data && chown -R sub2api:sub2api /app
# Switch to non-root user
USER sub2api
# Expose port (can be overridden by SERVER_PORT env var)
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD curl -f http://localhost:${SERVER_PORT:-8080}/health || exit 1
# Run the application
ENTRYPOINT ["/app/sub2api"]

View File

@@ -249,32 +249,64 @@ gateway:
# name: "Custom Profile 2"
# =============================================================================
# Sora2API Configuration
# Sora2API 配置
# Sora Direct Client Configuration
# Sora 直连配置
# =============================================================================
sora2api:
# Sora2API base URL
# Sora2API 服务地址
base_url: "http://127.0.0.1:8000"
# Sora2API API Key (for /v1/chat/completions and /v1/models)
# Sora2API API Key用于生成/模型列表)
api_key: ""
# Admin username/password (for token sync)
# 管理口用户名/密码(用于 token 同步)
admin_username: "admin"
admin_password: "admin"
# Admin token cache ttl (seconds)
# 管理口 token 缓存时长(秒)
admin_token_ttl_seconds: 900
# Admin request timeout (seconds)
# 管理口请求超时(秒)
admin_timeout_seconds: 10
# Token import mode: at/offline
# Token 导入模式at/offline
token_import_mode: "at"
# cipher_suites: [4866, 4867, 4865, 49199, 49195, 49200, 49196]
# curves: [29, 23, 24]
# point_formats: [0]
sora:
client:
# Sora backend base URL
# Sora 上游 Base URL
base_url: "https://sora.chatgpt.com/backend"
# Request timeout (seconds)
# 请求超时(秒)
timeout_seconds: 120
# Max retries for upstream requests
# 上游请求最大重试次数
max_retries: 3
# Poll interval (seconds)
# 轮询间隔(秒)
poll_interval_seconds: 2
# Max poll attempts
# 最大轮询次数
max_poll_attempts: 600
# Enable debug logs for Sora upstream requests
# 启用 Sora 直连调试日志
debug: false
# Optional custom headers (key-value)
# 额外请求头(键值对)
headers: {}
# Default User-Agent for Sora requests
# Sora 默认 User-Agent
user_agent: "Sora/1.2026.007 (Android 15; 24122RKC7C; build 2600700)"
# Disable TLS fingerprint for Sora upstream
# 关闭 Sora 上游 TLS 指纹伪装
disable_tls_fingerprint: false
storage:
# Storage type (local only for now)
# 存储类型(首发仅支持 local
type: "local"
# Local base path; empty uses /app/data/sora
# 本地存储基础路径;为空使用 /app/data/sora
local_path: ""
# Fallback to upstream URL when download fails
# 下载失败时回退到上游 URL
fallback_to_upstream: true
# Max concurrent downloads
# 并发下载上限
max_concurrent_downloads: 4
# Enable debug logs for media storage
# 启用媒体存储调试日志
debug: false
cleanup:
# Enable cleanup task
# 启用清理任务
enabled: true
# Retention days
# 保留天数
retention_days: 7
# Cron schedule
# Cron 调度表达式
schedule: "0 3 * * *"
# =============================================================================
# API Key Auth Cache Configuration