index.js 2.56 KB
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const http = require('http');
const config = require('./config');

const app = express();
const server = http.createServer(app);

// ─── 中间件 ───
app.use(cors(config.cors));
app.use(cookieParser());

// 控制字符净化:Agent 通过 curl 发送的 JSON body 可能含原始换行符导致解析失败
app.use((req, res, next) => {
  if (req.headers['content-type']?.includes('application/json')) {
    let rawBody = '';
    req.on('data', chunk => rawBody += chunk);
    req.on('end', () => {
      if (!rawBody) return next();
      try {
        req.body = JSON.parse(rawBody);
        req._bodyParsed = true;
        next();
      } catch (e) {
        try {
          // eslint-disable-next-line no-control-regex
          const cleaned = rawBody.replace(/[\x00-\x1F\x7F]/g, (ch) => {
            if (ch === '\n') return '\\n';
            if (ch === '\r') return '\\r';
            if (ch === '\t') return '\\t';
            return '';
          });
          req.body = JSON.parse(cleaned);
          req._bodyParsed = true;
          next();
        } catch (e2) {
          res.status(400).json({ error: 'Invalid JSON: ' + e2.message });
        }
      }
    });
  } else {
    next();
  }
});
app.use((req, res, next) => {
  if (req._bodyParsed) return next();
  express.json()(req, res, next);
});

app.use((err, req, res, next) => {
  if (err instanceof SyntaxError && err['status'] === 400 && 'body' in err) {
    return res.status(400).json({ error: 'Invalid JSON', details: err.message });
  }
  next(err);
});

// ─── API 路由 ───
app.use('/api/config', require('./routes/config'));
app.use('/api/master', require('./routes/master-chat'));

// ─── 系统端点 ───
app.get('/api/health', (req, res) => res.json({
  status: 'ok', timestamp: new Date().toISOString(),
}));

app.use((err, req, res, next) => {
  console.error('Server error:', err);
  res.status(500).json({ error: err.message });
});

// ─── 启动 ───
async function start() {
  try {
    const host = config.host || '0.0.0.0';
    server.listen(Number(config.port), host, () => {
      console.log(`✅ LemonACP 启动: http://${host}:${config.port}`);
    });
  } catch (error) {
    console.error('Failed to start server:', error);
    process.exit(1);
  }
}

process.on('SIGTERM', () => { console.log('\n正在关闭...'); process.exit(0); });
process.on('SIGINT',  () => { console.log('\n正在关闭...'); process.exit(0); });

start();
module.exports = app;