|
|
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' }));
|
|
|
|
|
|
|
|
|
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)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
req.requestId = requestId
|
|
|
|
|
|
|
|
|
console.log(`[INFO] [${requestId}] [${clientIp}] ${req.method} ${req.path}`)
|
|
|
|
|
|
|
|
|
const originalJson = res.json.bind(res)
|
|
|
const originalEnd = res.end.bind(res)
|
|
|
|
|
|
|
|
|
res.json = function(data) {
|
|
|
logRequestEnd(req, res, startTime, requestId, clientIp)
|
|
|
return originalJson(data)
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
})();
|
|
|
|