File size: 4,796 Bytes
6dfd5ec afb7d7b 6dfd5ec afb7d7b 6dfd5ec afb7d7b 6dfd5ec |
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 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
import express from 'express';
import { loadConfig, isDevMode, getPort } from './config.js';
import { logInfo, logError } from './logger.js';
import router from './routes.js';
import { initializeAuth, accessKeyMiddleware } from './auth.js';
const app = express();
app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
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();
});
// 入站 API Key 鉴权:仅保护 /v1/* 路由
app.use('/v1', accessKeyMiddleware);
app.use(router);
app.get('/', (req, res) => {
res.json({
name: 'droid2api',
version: '1.0.0',
description: 'OpenAI Compatible API Proxy',
endpoints: [
'GET /v1/models',
'POST /v1/chat/completions',
'POST /v1/responses',
'POST /v1/messages'
]
});
});
// 404 处理 - 捕获所有未匹配的路由
app.use((req, res, next) => {
const errorInfo = {
timestamp: new Date().toISOString(),
method: req.method,
url: req.originalUrl || req.url,
path: req.path,
query: req.query,
params: req.params,
body: req.body,
headers: {
'content-type': req.headers['content-type'],
'user-agent': req.headers['user-agent'],
'origin': req.headers['origin'],
'referer': req.headers['referer']
},
ip: req.ip || req.connection.remoteAddress
};
console.error('\n' + '='.repeat(80));
console.error('❌ 非法请求地址');
console.error('='.repeat(80));
console.error(`时间: ${errorInfo.timestamp}`);
console.error(`方法: ${errorInfo.method}`);
console.error(`地址: ${errorInfo.url}`);
console.error(`路径: ${errorInfo.path}`);
if (Object.keys(errorInfo.query).length > 0) {
console.error(`查询参数: ${JSON.stringify(errorInfo.query, null, 2)}`);
}
if (errorInfo.body && Object.keys(errorInfo.body).length > 0) {
console.error(`请求体: ${JSON.stringify(errorInfo.body, null, 2)}`);
}
console.error(`客户端IP: ${errorInfo.ip}`);
console.error(`User-Agent: ${errorInfo.headers['user-agent'] || 'N/A'}`);
if (errorInfo.headers.referer) {
console.error(`来源: ${errorInfo.headers.referer}`);
}
console.error('='.repeat(80) + '\n');
logError('Invalid request path', errorInfo);
res.status(404).json({
error: 'Not Found',
message: `路径 ${req.method} ${req.path} 不存在`,
timestamp: errorInfo.timestamp,
availableEndpoints: [
'GET /v1/models',
'POST /v1/chat/completions',
'POST /v1/responses',
'POST /v1/messages'
]
});
});
// 错误处理中间件
app.use((err, req, res, next) => {
logError('Unhandled error', err);
res.status(500).json({
error: 'Internal server error',
message: isDevMode() ? err.message : undefined
});
});
(async () => {
try {
loadConfig();
logInfo('Configuration loaded successfully');
logInfo(`Dev mode: ${isDevMode()}`);
// Initialize auth system (load and setup API key if needed)
// This won't throw error if no auth config is found - will use client auth
await initializeAuth();
const PORT = getPort();
logInfo(`Starting server on port ${PORT}...`);
const server = app.listen(PORT)
.on('listening', () => {
logInfo(`Server running on http://localhost:${PORT}`);
logInfo('Available endpoints:');
logInfo(' GET /v1/models');
logInfo(' POST /v1/chat/completions');
logInfo(' POST /v1/responses');
logInfo(' POST /v1/messages');
})
.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`\n${'='.repeat(80)}`);
console.error(`ERROR: Port ${PORT} is already in use!`);
console.error('');
console.error('Please choose one of the following options:');
console.error(` 1. Stop the process using port ${PORT}:`);
console.error(` lsof -ti:${PORT} | xargs kill`);
console.error('');
console.error(' 2. Change the port in config.json:');
console.error(' Edit config.json and modify the "port" field');
console.error(`${'='.repeat(80)}\n`);
process.exit(1);
} else {
logError('Failed to start server', err);
process.exit(1);
}
});
} catch (error) {
logError('Failed to start server', error);
process.exit(1);
}
})();
|