e-scooter-rental-system/server/index.js

90 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const app = express();
const PORT = process.env.PORT || 3000;
// ─── 安全中间件 ──────────────────────────────────────────────
// helmet: 安全响应头
app.use(helmet());
// CORS: 白名单域名
const allowedOrigins = (process.env.ALLOWED_ORIGINS || 'http://localhost:5173')
.split(',')
.map((o) => o.trim());
app.use(cors({
origin: allowedOrigins,
credentials: true
}));
// 请求体大小限制防止大body攻击
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
// 全局限流(所有 API
const globalLimiter = rateLimit({
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000,
max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS) || 100,
standardHeaders: true,
legacyHeaders: false,
message: { success: false, message: '请求过于频繁,请稍后再试' }
});
app.use('/api', globalLimiter);
// 登录接口更严格的限流(单独限流器)
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 20,
standardHeaders: true,
legacyHeaders: false,
message: { success: false, message: '登录尝试过于频繁请15分钟后再试' }
});
// ─── 连接 MongoDB ────────────────────────────────────────────
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/e-scooter-rental')
.then(() => console.log('✅ MongoDB 连接成功'))
.catch(err => console.error('❌ MongoDB 连接失败:', err.message));
// ─── 路由 ───────────────────────────────────────────────────
app.use('/api/vehicles', require('./routes/vehicles'));
app.use('/api/orders', require('./routes/orders'));
app.use('/api/customers', require('./routes/customers'));
app.use('/api/finance', require('./routes/finance'));
app.use('/api/stores', require('./routes/stores'));
app.use('/api/complaints', require('./routes/complaints'));
app.use('/api/approvals', require('./routes/approvals'));
app.use('/api/payments', require('./routes/payments'));
app.use('/api/conflicts', require('./routes/conflicts'));
app.use('/api/applications', require('./routes/applications'));
app.use('/api/disputes', require('./routes/disputes'));
app.use('/api/riders', require('./routes/riders'));
app.use('/api/vehicle-types', require('./routes/vehicleTypes'));
// ─── 健康检查(不限流) ─────────────────────────────────────
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// ─── 404 处理 ───────────────────────────────────────────────
app.use((req, res) => {
res.status(404).json({
success: false,
message: '接口不存在',
path: req.path
});
});
// ─── 错误处理中间件 ─────────────────────────────────────────
const errorHandler = require('./middleware/errorHandler');
app.use(errorHandler);
// ─── 启动 ───────────────────────────────────────────────────
app.listen(PORT, () => {
console.log(`🚀 服务器运行在 http://localhost:${PORT}`);
});