File size: 3,897 Bytes
0133533
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import express from 'express'
import { getPort } from './configs/config.js'
import router from './routes/routes.js'

const app = express();

app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true, limit: '50mb' }));

// 生成请求ID (UUID格式)
function generateRequestId() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    const r = Math.random() * 16 | 0
    const v = c === 'x' ? r : (r & 0x3 | 0x8)
    return v.toString(16)
  })
}

// 获取客户端IP
function getClientIp(req) {
  return req.headers['x-forwarded-for']?.split(',')[0].trim() ||
         req.headers['x-real-ip'] ||
         req.connection?.remoteAddress ||
         req.socket?.remoteAddress ||
         'unknown'
}

// 请求日志中间件
app.use((req, res, next) => {
  const startTime = Date.now()
  const requestId = generateRequestId()
  const clientIp = getClientIp(req)

  // 将请求ID附加到req对象
  req.requestId = requestId

  // 请求开始时打印日志
  console.log(`[INFO] [${requestId}] [${clientIp}] ${req.method} ${req.path}`)

  // 保存原始的 res.json 和 res.end 方法
  const originalJson = res.json.bind(res)
  const originalEnd = res.end.bind(res)

  // 重写 res.json 方法以捕获响应状态
  res.json = function(data) {
    logRequestEnd(req, res, startTime, requestId, clientIp)
    return originalJson(data)
  }

  // 重写 res.end 方法以捕获流式响应状态
  res.end = function(...args) {
    logRequestEnd(req, res, startTime, requestId, clientIp)
    return originalEnd(...args)
  }

  next()
})

// 请求结束日志记录函数
function logRequestEnd(req, res, startTime, requestId, clientIp) {
  // 避免重复记录
  if (res._logged) return
  res._logged = true

  const duration = ((Date.now() - startTime) / 1000).toFixed(3)
  const status = res.statusCode

  console.log(`[INFO] [${requestId}] [${clientIp}] 响应状态: ${status}`)
  console.log(`[INFO] [${requestId}] [${clientIp}] 处理时间: ${duration}s`)
}

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key, anthropic-version');

  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});

app.use(router);

app.get('/', (req, res) => {
  res.redirect('https://www.bilibili.com/video/BV1SMH5zfEwe/?spm_id_from=333.1007.tianma.1-1-1.click&vd_source=1f3b8eb28230105c578a443fa6481550')
})


// 错误处理中间件
app.use((err, req, res, next) => {
  console.error('未处理的错误:', err);
  res.status(500).json({
    error: '内部服务器错误',
    message: err.message
  });
});

(async () => {
  try {
    const PORT = getPort()

    app.listen(PORT)
    .on('listening', () => {
      console.log(`服务器运行在 http://localhost:${PORT}`)
    })
    .on('error', (err) => {
      if (err.code === 'EADDRINUSE') {
        console.error(`\n${'='.repeat(80)}`);
        console.error(`错误: 端口 ${PORT} 已被占用!`);
        console.error('');
        console.error('请选择以下选项之一:');
        console.error(`  1. 停止使用端口 ${PORT} 的进程:`);
        console.error(`     lsof -ti:${PORT} | xargs kill`);
        console.error('');
        console.error('  2. 使用环境变量更改端口:');
        console.error('     export PORT=8080');
        console.error(`${'='.repeat(80)}\n`);
        process.exit(1);
      } else {
        console.error('启动服务器失败:', err);
        process.exit(1);
      }
    });
  } catch (error) {
    console.error('启动服务器失败:', error);
    process.exit(1);
  }
})();