const express = require('express'); const morgan = require('morgan'); const { createProxyMiddleware } = require('http-proxy-middleware'); const axios = require('axios'); const url = require('url'); const app = express(); // 启用日志 app.use(morgan('dev')); // 环境变量配置 const PORT = process.env.HF_PORT || 7860; const TARGET_URL = process.env.TARGET_URL || 'http://localhost:3010'; const API_PATH = process.env.API_PATH || '/v1'; const TIMEOUT = parseInt(process.env.TIMEOUT) || 30000; console.log(`Service configuration: - Port: ${PORT} - Target URL: ${TARGET_URL} - API Path: ${API_PATH} - Timeout: ${TIMEOUT}ms`); // 解析代理设置 let proxyPool = []; if (process.env.PROXY) { proxyPool = process.env.PROXY.split(',').map(p => p.trim()).filter(p => p); console.log(`Loaded ${proxyPool.length} proxies from environment`); if (proxyPool.length > 0) { console.log('Proxy pool initialized:'); proxyPool.forEach((proxy, index) => { // 隐藏敏感信息的日志 const maskedProxy = proxy.replace(/(https?:\/\/)([^:]+):([^@]+)@/, '$1$2:****@'); console.log(` [${index + 1}] ${maskedProxy}`); }); } } // 从代理池中随机选择一个代理 function getRandomProxy() { if (proxyPool.length === 0) return null; const randomIndex = Math.floor(Math.random() * proxyPool.length); const proxyUrl = proxyPool[randomIndex]; const parsedUrl = url.parse(proxyUrl); return { host: parsedUrl.hostname, port: parsedUrl.port || 80, auth: parsedUrl.auth ? { username: parsedUrl.auth.split(':')[0], password: parsedUrl.auth.split(':')[1] } : undefined }; } // 模型列表 API app.get('/hf/v1/models', (req, res) => { const models = { "object": "list", "data": [ { "id": "claude-3.5-sonnet", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-4", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-4o", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "claude-3-opus", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-3.5-turbo", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-4-turbo-2024-04-09", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-4o-128k", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gemini-1.5-flash-500k", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "claude-3-haiku-200k", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "claude-3-5-sonnet-200k", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "claude-3-5-sonnet-20241022", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gpt-4o-mini", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "o1-mini", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "o1-preview", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "o1", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "claude-3.5-haiku", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gemini-exp-1206", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gemini-2.0-flash-thinking-exp", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "gemini-2.0-flash-exp", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "deepseek-v3", "object": "model", "created": 1706745938, "owned_by": "cursor" }, { "id": "deepseek-r1", "object": "model", "created": 1706745938, "owned_by": "cursor" } ] }; res.json(models); }); // 代理转发,使用动态代理池 app.use('/hf/v1/chat/completions', (req, res, next) => { const proxy = getRandomProxy(); const targetEndpoint = `${TARGET_URL}${API_PATH}/chat/completions`; console.log(`Forwarding request to: ${targetEndpoint}`); const middleware = createProxyMiddleware({ target: targetEndpoint, changeOrigin: true, proxy: proxy ? proxy : undefined, timeout: TIMEOUT, proxyTimeout: TIMEOUT, onProxyReq: (proxyReq, req, res) => { if (req.body) { const bodyData = JSON.stringify(req.body); proxyReq.setHeader('Content-Type', 'application/json'); proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData)); proxyReq.write(bodyData); proxyReq.end(); } }, onError: (err, req, res) => { console.error('Proxy error:', err); res.status(500).json({ error: { message: 'Proxy error occurred', type: 'proxy_error', details: process.env.NODE_ENV === 'development' ? err.message : undefined } }); }, onProxyRes: (proxyRes, req, res) => { console.log(`Proxy response status: ${proxyRes.statusCode}`); } }); if (proxy) { const maskedProxy = `${proxy.host}:${proxy.port}` + (proxy.auth ? ' (with auth)' : ''); console.log(`Using proxy: ${maskedProxy}`); } else { console.log('Direct connection (no proxy)'); } middleware(req, res, next); }); // 首页 app.get('/', (req, res) => { const htmlContent = ` Cursor To OpenAI

Cursor To OpenAI Server

高性能 AI 模型代理服务

服务正在运行

配置信息

服务环境
环境变量配置模式
自定义端点(基本URL)
目标服务
${TARGET_URL}${API_PATH}
代理状态
${proxyPool.length > 0 ? `使用中 (${proxyPool.length}个代理)` : '未启用'}

支持的模型列表

使用说明

在客户端配置以下信息:

API URL: http://{服务器地址}:${PORT}/hf/v1
API Key: 您的API密钥

支持兼容OpenAI格式的请求,已预配置转发到${TARGET_URL}${API_PATH}

`; res.send(htmlContent); }); // 健康检查端点 app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', time: new Date().toISOString(), proxyCount: proxyPool.length, target: `${TARGET_URL}${API_PATH}` }); }); // 启动服务 app.listen(PORT, () => { console.log(`HF Proxy server is running at PORT: ${PORT}`); console.log(`Target service: ${TARGET_URL}${API_PATH}`); console.log(`Proxy status: ${proxyPool.length > 0 ? 'Enabled' : 'Disabled'}`); });