isididiidid commited on
Commit
6a707b0
·
verified ·
1 Parent(s): 9ea88cd

Update hf.js

Browse files
Files changed (1) hide show
  1. hf.js +109 -59
hf.js CHANGED
@@ -2,15 +2,39 @@ const express = require('express');
2
  const morgan = require('morgan');
3
  const { createProxyMiddleware } = require('http-proxy-middleware');
4
  const axios = require('axios');
5
- const fs = require('fs');
6
  const url = require('url');
7
  const app = express();
8
 
 
9
  app.use(morgan('dev'));
10
 
11
- // 全局代理池
12
- let proxyPool = process.env.PROXY ? process.env.PROXY.split(',').map(p => p.trim()) : [];
13
- console.log('Initial proxy pool:', proxyPool);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  // 从代理池中随机选择一个代理
16
  function getRandomProxy() {
@@ -29,46 +53,6 @@ function getRandomProxy() {
29
  };
30
  }
31
 
32
- // 配置 axios 的代理
33
- function configureAxiosProxy() {
34
- const proxy = getRandomProxy();
35
- if (proxy) {
36
- axios.defaults.proxy = proxy;
37
- console.log(`Axios using proxy: ${proxy.host}:${proxy.port}`);
38
- } else {
39
- delete axios.defaults.proxy;
40
- console.log('No proxy available for axios');
41
- }
42
- }
43
-
44
- // 从外部 API 更新代理池
45
- async function updateProxyPool() {
46
- const proxyApiUrl = process.env.PROXY_API_URL || 'http://example.com/api/proxies';
47
- try {
48
- const response = await axios.get(proxyApiUrl);
49
- // 假设 API 返回格式为 { proxies: ["http://user:pass@host:port", ...] }
50
- const newProxies = response.data.proxies || [];
51
- if (newProxies.length > 0) {
52
- proxyPool = newProxies;
53
- console.log('Proxy pool updated:', proxyPool);
54
- configureAxiosProxy(); // 更新 axios 代理
55
- } else {
56
- console.warn('No proxies received from API');
57
- }
58
- } catch (error) {
59
- console.error('Failed to update proxy pool:', error.message);
60
- }
61
- }
62
-
63
- // 定期更新代理池
64
- const updateInterval = parseInt(process.env.PROXY_UPDATE_INTERVAL) || 300; // 默认 5 分钟
65
- if (updateInterval > 0) {
66
- setInterval(updateProxyPool, updateInterval * 1000);
67
- console.log(`Proxy pool will update every ${updateInterval} seconds`);
68
- // 启动时立即更新一次
69
- updateProxyPool();
70
- }
71
-
72
  // 模型列表 API
73
  app.get('/hf/v1/models', (req, res) => {
74
  const models = {
@@ -208,12 +192,16 @@ app.get('/hf/v1/models', (req, res) => {
208
  // 代理转发,使用动态代理池
209
  app.use('/hf/v1/chat/completions', (req, res, next) => {
210
  const proxy = getRandomProxy();
 
 
 
 
211
  const middleware = createProxyMiddleware({
212
- target: 'http://localhost:3010/v1/chat/completions', // 可替换为实际目标服务
213
  changeOrigin: true,
214
  proxy: proxy ? proxy : undefined,
215
- timeout: 30000, // 超时 30 秒
216
- proxyTimeout: 30000, // 代理超时 30 秒
217
  onProxyReq: (proxyReq, req, res) => {
218
  if (req.body) {
219
  const bodyData = JSON.stringify(req.body);
@@ -225,14 +213,26 @@ app.use('/hf/v1/chat/completions', (req, res, next) => {
225
  },
226
  onError: (err, req, res) => {
227
  console.error('Proxy error:', err);
228
- res.status(500).send('Proxy error occurred');
 
 
 
 
 
 
 
 
 
229
  }
230
  });
 
231
  if (proxy) {
232
- console.log(`Request proxied via ${proxy.host}:${proxy.port}`);
 
233
  } else {
234
- console.log('No proxy available, direct connection');
235
  }
 
236
  middleware(req, res, next);
237
  });
238
 
@@ -296,6 +296,16 @@ app.get('/', (req, res) => {
296
  color: var(--primary-color);
297
  font-weight: 500;
298
  }
 
 
 
 
 
 
 
 
 
 
299
  .models {
300
  background: var(--card-bg);
301
  padding: 25px;
@@ -336,6 +346,19 @@ app.get('/', (req, res) => {
336
  background: #f1f5f9;
337
  border-radius: 4px;
338
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
339
  @media (max-width: 768px) {
340
  body {
341
  padding: 10px;
@@ -351,31 +374,48 @@ app.get('/', (req, res) => {
351
  <div class="header">
352
  <h1>Cursor To OpenAI Server</h1>
353
  <p>高性能 AI 模型代理服务</p>
 
354
  </div>
 
355
  <div class="info">
356
  <h2>配置信息</h2>
357
  <div class="info-item">
358
- <div class="info-label">聊天来源</div>
359
- <div class="info-value">自定义(兼容 OpenAI)</div>
360
  </div>
361
  <div class="info-item">
362
  <div class="info-label">自定义端点(基本URL)</div>
363
  <div class="info-value" id="endpoint-url"></div>
364
  </div>
365
  <div class="info-item">
366
- <div class="info-label">自定义API密钥</div>
367
- <div class="info-value">抓取的Cursor Cookie,格式为user_...</div>
 
 
 
 
368
  </div>
369
  </div>
 
370
  <div class="models">
371
  <h3>支持的模型列表</h3>
372
  <div id="model-list"></div>
373
  </div>
 
 
 
 
 
 
 
 
374
  </div>
 
375
  <script>
376
  const url = new URL(window.location.href);
377
  const link = url.protocol + '//' + url.host + '/hf/v1';
378
  document.getElementById('endpoint-url').textContent = link;
 
379
  fetch(link + '/models')
380
  .then(response => response.json())
381
  .then(data => {
@@ -401,11 +441,21 @@ app.get('/', (req, res) => {
401
  res.send(htmlContent);
402
  });
403
 
404
- // 启动服务前配置初始 axios 代理
405
- configureAxiosProxy();
 
 
 
 
 
 
 
406
 
407
- const port = process.env.HF_PORT || 7860;
408
- app.listen(port, () => {
409
- console.log(`HF Proxy server is running at PORT: ${port}`);
 
 
410
  });
411
 
 
 
2
  const morgan = require('morgan');
3
  const { createProxyMiddleware } = require('http-proxy-middleware');
4
  const axios = require('axios');
 
5
  const url = require('url');
6
  const app = express();
7
 
8
+ // 启用日志
9
  app.use(morgan('dev'));
10
 
11
+ // 环境变量配置
12
+ const PORT = process.env.HF_PORT || 7860;
13
+ const TARGET_URL = process.env.TARGET_URL || 'http://localhost:3010';
14
+ const API_PATH = process.env.API_PATH || '/v1';
15
+ const TIMEOUT = parseInt(process.env.TIMEOUT) || 30000;
16
+
17
+ console.log(`Service configuration:
18
+ - Port: ${PORT}
19
+ - Target URL: ${TARGET_URL}
20
+ - API Path: ${API_PATH}
21
+ - Timeout: ${TIMEOUT}ms`);
22
+
23
+ // 解析代理设置
24
+ let proxyPool = [];
25
+ if (process.env.PROXY) {
26
+ proxyPool = process.env.PROXY.split(',').map(p => p.trim()).filter(p => p);
27
+ console.log(`Loaded ${proxyPool.length} proxies from environment`);
28
+
29
+ if (proxyPool.length > 0) {
30
+ console.log('Proxy pool initialized:');
31
+ proxyPool.forEach((proxy, index) => {
32
+ // 隐藏敏感信息的日志
33
+ const maskedProxy = proxy.replace(/(https?:\/\/)([^:]+):([^@]+)@/, '$1$2:****@');
34
+ console.log(` [${index + 1}] ${maskedProxy}`);
35
+ });
36
+ }
37
+ }
38
 
39
  // 从代理池中随机选择一个代理
40
  function getRandomProxy() {
 
53
  };
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  // 模型列表 API
57
  app.get('/hf/v1/models', (req, res) => {
58
  const models = {
 
192
  // 代理转发,使用动态代理池
193
  app.use('/hf/v1/chat/completions', (req, res, next) => {
194
  const proxy = getRandomProxy();
195
+ const targetEndpoint = `${TARGET_URL}${API_PATH}/chat/completions`;
196
+
197
+ console.log(`Forwarding request to: ${targetEndpoint}`);
198
+
199
  const middleware = createProxyMiddleware({
200
+ target: targetEndpoint,
201
  changeOrigin: true,
202
  proxy: proxy ? proxy : undefined,
203
+ timeout: TIMEOUT,
204
+ proxyTimeout: TIMEOUT,
205
  onProxyReq: (proxyReq, req, res) => {
206
  if (req.body) {
207
  const bodyData = JSON.stringify(req.body);
 
213
  },
214
  onError: (err, req, res) => {
215
  console.error('Proxy error:', err);
216
+ res.status(500).json({
217
+ error: {
218
+ message: 'Proxy error occurred',
219
+ type: 'proxy_error',
220
+ details: process.env.NODE_ENV === 'development' ? err.message : undefined
221
+ }
222
+ });
223
+ },
224
+ onProxyRes: (proxyRes, req, res) => {
225
+ console.log(`Proxy response status: ${proxyRes.statusCode}`);
226
  }
227
  });
228
+
229
  if (proxy) {
230
+ const maskedProxy = `${proxy.host}:${proxy.port}` + (proxy.auth ? ' (with auth)' : '');
231
+ console.log(`Using proxy: ${maskedProxy}`);
232
  } else {
233
+ console.log('Direct connection (no proxy)');
234
  }
235
+
236
  middleware(req, res, next);
237
  });
238
 
 
296
  color: var(--primary-color);
297
  font-weight: 500;
298
  }
299
+ .service-status {
300
+ background: #dcfce7;
301
+ border: 1px solid #86efac;
302
+ color: #166534;
303
+ padding: 8px 12px;
304
+ border-radius: 6px;
305
+ font-size: 0.95em;
306
+ display: inline-block;
307
+ margin: 15px 0;
308
+ }
309
  .models {
310
  background: var(--card-bg);
311
  padding: 25px;
 
346
  background: #f1f5f9;
347
  border-radius: 4px;
348
  }
349
+ .details {
350
+ margin-top: 20px;
351
+ background: #f8fafc;
352
+ padding: 15px;
353
+ border-radius: 8px;
354
+ border: 1px solid #e5e7eb;
355
+ }
356
+ .details pre {
357
+ background: #f1f5f9;
358
+ padding: 10px;
359
+ border-radius: 6px;
360
+ overflow-x: auto;
361
+ }
362
  @media (max-width: 768px) {
363
  body {
364
  padding: 10px;
 
374
  <div class="header">
375
  <h1>Cursor To OpenAI Server</h1>
376
  <p>高性能 AI 模型代理服务</p>
377
+ <div class="service-status">服务正在运行</div>
378
  </div>
379
+
380
  <div class="info">
381
  <h2>配置信息</h2>
382
  <div class="info-item">
383
+ <div class="info-label">服务环境</div>
384
+ <div class="info-value">环境变量配置模式</div>
385
  </div>
386
  <div class="info-item">
387
  <div class="info-label">自定义端点(基本URL)</div>
388
  <div class="info-value" id="endpoint-url"></div>
389
  </div>
390
  <div class="info-item">
391
+ <div class="info-label">目标服务</div>
392
+ <div class="info-value">${TARGET_URL}${API_PATH}</div>
393
+ </div>
394
+ <div class="info-item">
395
+ <div class="info-label">代理状态</div>
396
+ <div class="info-value">${proxyPool.length > 0 ? `使用中 (${proxyPool.length}个代理)` : '未启用'}</div>
397
  </div>
398
  </div>
399
+
400
  <div class="models">
401
  <h3>支持的模型列表</h3>
402
  <div id="model-list"></div>
403
  </div>
404
+
405
+ <div class="details">
406
+ <h3>使用说明</h3>
407
+ <p>在客户端配置以下信息:</p>
408
+ <pre>API URL: http://{服务器地址}:${PORT}/hf/v1
409
+ API Key: 您的API密钥</pre>
410
+ <p>支持兼容OpenAI格式的请求,已预配置转发到${TARGET_URL}${API_PATH}</p>
411
+ </div>
412
  </div>
413
+
414
  <script>
415
  const url = new URL(window.location.href);
416
  const link = url.protocol + '//' + url.host + '/hf/v1';
417
  document.getElementById('endpoint-url').textContent = link;
418
+
419
  fetch(link + '/models')
420
  .then(response => response.json())
421
  .then(data => {
 
441
  res.send(htmlContent);
442
  });
443
 
444
+ // 健康检查端点
445
+ app.get('/health', (req, res) => {
446
+ res.status(200).json({
447
+ status: 'ok',
448
+ time: new Date().toISOString(),
449
+ proxyCount: proxyPool.length,
450
+ target: `${TARGET_URL}${API_PATH}`
451
+ });
452
+ });
453
 
454
+ // 启动服务
455
+ app.listen(PORT, () => {
456
+ console.log(`HF Proxy server is running at PORT: ${PORT}`);
457
+ console.log(`Target service: ${TARGET_URL}${API_PATH}`);
458
+ console.log(`Proxy status: ${proxyPool.length > 0 ? 'Enabled' : 'Disabled'}`);
459
  });
460
 
461
+