- Claude API 路由从 /v1/* 改为 /claude/* - OpenAI API 路由从 /openai/v1/* 改为 /openai/* - 更清晰的端点命名,便于区分不同提供商 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>
55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import 'dotenv/config';
|
||
import express from 'express';
|
||
import { proxyHandler } from './proxy.js';
|
||
import { openaiProxyHandler } from './proxy-openai.js';
|
||
import { healthHandler } from './health.js';
|
||
|
||
const app = express();
|
||
const PORT = parseInt(process.env.PORT || '80', 10);
|
||
|
||
// 解析 JSON 请求体,设置较大的限制以支持大请求
|
||
app.use(express.json({ limit: '50mb' }));
|
||
|
||
// 健康检查端点
|
||
app.get('/health', healthHandler);
|
||
|
||
// Claude API 代理路由: /claude/*
|
||
app.all('/claude/*', proxyHandler);
|
||
|
||
// OpenAI API 代理路由: /openai/*
|
||
app.all('/openai/*', openaiProxyHandler);
|
||
|
||
// 启动服务器
|
||
const server = app.listen(PORT, () => {
|
||
console.log(`API Proxy 服务已启动`);
|
||
console.log(`端口: ${PORT}`);
|
||
console.log(`Claude API: ${process.env.ANTHROPIC_BASE_URL || 'https://api.anthropic.com'}`);
|
||
console.log(`OpenAI API: ${process.env.OPENAI_BASE_URL || 'https://api.openai.com'}`);
|
||
console.log(`健康检查: http://localhost:${PORT}/health`);
|
||
});
|
||
|
||
// 优雅关闭处理
|
||
let isShuttingDown = false;
|
||
|
||
function gracefulShutdown(signal: string) {
|
||
if (isShuttingDown) return;
|
||
isShuttingDown = true;
|
||
|
||
console.log(`\n收到 ${signal} 信号,开始优雅关闭...`);
|
||
|
||
// 停止接受新连接
|
||
server.close(() => {
|
||
console.log('服务器已关闭');
|
||
process.exit(0);
|
||
});
|
||
|
||
// 强制退出超时(K8S 默认 30 秒宽限期)
|
||
setTimeout(() => {
|
||
console.log('优雅关闭超时,强制退出');
|
||
process.exit(1);
|
||
}, 25000);
|
||
}
|
||
|
||
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
||
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|