Refactor giai đoạn 1: test các tính năng vừa thay đổi như tour, scene...
This commit is contained in:
+29
-89
@@ -1,110 +1,50 @@
|
||||
require('dotenv').config();
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
|
||||
const dotenv = require('dotenv');
|
||||
const connectDB = require('./config/db');
|
||||
const authRoutes = require('./routes/authRoutes');
|
||||
const apiRoutes = require('./routes/apiRoutes');
|
||||
|
||||
// Khởi động Image Processing Worker
|
||||
require('./routes/imageWorker');
|
||||
// Cấu hình môi trường
|
||||
dotenv.config();
|
||||
|
||||
// Connect to Database
|
||||
// Kiểm tra các biến môi trường bắt buộc
|
||||
const requiredEnvs = ['MONGODB_URI', 'JWT_SECRET'];
|
||||
requiredEnvs.forEach(env => {
|
||||
if (!process.env[env]) {
|
||||
console.error(`[CRITICAL] Thiếu biến môi trường bắt buộc: ${env}`);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Kết nối cơ sở dữ liệu MongoDB
|
||||
connectDB();
|
||||
|
||||
const app = express();
|
||||
|
||||
// Standard middlewares
|
||||
// Chuẩn bị danh sách các origin được phép cho CORS
|
||||
const primarySystemHost = process.env.SYSTEM_HOST || 'http://localhost:5000';
|
||||
let configuredAllowedOrigins = [];
|
||||
|
||||
// Thêm SYSTEM_HOST chính
|
||||
try {
|
||||
configuredAllowedOrigins.push(new URL(primarySystemHost).origin);
|
||||
} catch (e) {
|
||||
console.warn(`[CORS Config Warning] Malformed SYSTEM_HOST: ${primarySystemHost}. Using as-is.`);
|
||||
configuredAllowedOrigins.push(primarySystemHost);
|
||||
}
|
||||
|
||||
// Thêm các origin bổ sung từ biến môi trường ADDITIONAL_ALLOWED_ORIGINS (cách nhau bởi dấu phẩy)
|
||||
if (process.env.ADDITIONAL_ALLOWED_ORIGINS) {
|
||||
process.env.ADDITIONAL_ALLOWED_ORIGINS.split(',').forEach(originStr => {
|
||||
try {
|
||||
configuredAllowedOrigins.push(new URL(originStr.trim()).origin);
|
||||
} catch (e) {
|
||||
console.warn(`[CORS Config Warning] Malformed origin in ADDITIONAL_ALLOWED_ORIGINS: ${originStr.trim()}. Skipping.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const corsOptions = {
|
||||
origin: function (origin, callback) {
|
||||
// Cho phép các request không có origin (như Postman hoặc khi render phía server)
|
||||
if (!origin) return callback(null, true);
|
||||
|
||||
let incomingOrigin;
|
||||
try {
|
||||
incomingOrigin = new URL(origin).origin;
|
||||
} catch (e) {
|
||||
incomingOrigin = origin;
|
||||
}
|
||||
|
||||
// Kiểm tra nếu incomingOrigin nằm trong danh sách các origin được cấu hình
|
||||
if (configuredAllowedOrigins.includes(incomingOrigin)) return callback(null, true);
|
||||
|
||||
// Trong môi trường dev, cho phép các biến thể localhost
|
||||
const isLocal = incomingOrigin.includes('localhost') || incomingOrigin.includes('127.0.0.1') || incomingOrigin.includes('::1');
|
||||
if (process.env.NODE_ENV !== 'production' && isLocal) {
|
||||
return callback(null, true);
|
||||
}
|
||||
|
||||
console.warn(`[CORS Blocked]: Origin ${origin} is not allowed by configuration.`);
|
||||
callback(new Error('Not allowed by CORS'));
|
||||
},
|
||||
credentials: true,
|
||||
maxAge: 86400 // Cho phép trình duyệt cache kết quả preflight OPTIONS trong 24 giờ
|
||||
};
|
||||
app.use(cors(corsOptions));
|
||||
// Middlewares cơ bản
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
|
||||
// Request Logger Middleware
|
||||
app.use((req, res, next) => {
|
||||
const start = Date.now();
|
||||
res.on('finish', () => {
|
||||
const duration = Date.now() - start;
|
||||
console.log(`[${new Date().toISOString()}] ${req.method} ${req.originalUrl} - ${res.statusCode} (${duration}ms)`);
|
||||
});
|
||||
next();
|
||||
});
|
||||
// Khởi tạo Worker xử lý ảnh (BullMQ + Redis)
|
||||
// Việc import này sẽ kích hoạt imageWorker.js lắng nghe hàng đợi 'image-processing'
|
||||
require('./routes/imageWorker');
|
||||
|
||||
// API Routes
|
||||
app.use('/api/auth', authRoutes);
|
||||
app.use('/api', apiRoutes);
|
||||
// Đăng ký các API Routes tập trung
|
||||
app.use('/api', require('./routes/apiRoutes'));
|
||||
|
||||
// Serve Frontend static assets from the parent/frontend directory
|
||||
// Phục vụ các tệp tĩnh từ thư mục frontend
|
||||
app.use(express.static(path.join(__dirname, '../frontend')));
|
||||
|
||||
// Fallback to index.html for single-page style behaviors
|
||||
app.use((req, res) => {
|
||||
// Hỗ trợ Single Page Application (SPA)
|
||||
// Mọi request không khớp với API hoặc File tĩnh sẽ trả về index.html
|
||||
app.get(/.*/, (req, res) => {
|
||||
res.sendFile(path.join(__dirname, '../frontend/index.html'));
|
||||
});
|
||||
|
||||
// Centralized JSON Error Handler (Ngăn chặn lỗi trả về HTML làm hỏng Frontend)
|
||||
app.use((err, req, res, next) => {
|
||||
console.error(`[Error Handler]: ${err.message}`);
|
||||
res.status(err.status || 500).json({
|
||||
message: err.message || 'Internal Server Error'
|
||||
});
|
||||
});
|
||||
|
||||
const PORT = process.env.PORT || 5000;
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running in ${process.env.NODE_ENV || 'development'} mode on port ${PORT}`);
|
||||
console.log(`CORS Allowed Origins: ${configuredAllowedOrigins.join(', ')}`);
|
||||
});
|
||||
// ... cuối file server.js
|
||||
module.exports = app;
|
||||
console.log(`================================================`);
|
||||
console.log(`🚀 Server 3D Tours đang chạy tại port: ${PORT}`);
|
||||
console.log(`🔧 Chế độ: ${process.env.NODE_ENV || 'development'}`);
|
||||
console.log(`================================================`);
|
||||
});
|
||||
Reference in New Issue
Block a user