const express = require('express'); const path = require('path'); const app = express(); const config = require('./config/app') const session = require('express-session'); const RedisStore = require('connect-redis')(session); const cookieParser = require('cookie-parser'); const bodyParser = require('body-parser'); const compression = require('compression'); const authChecker = require('./libs/auth/checker'); // const helmet = require('helmet'); // 安全中间件,主要添加一些安全头 const rateLimit = require('express-rate-limit'); // 速率限制,预防ddos攻击 // const cors = require('cors'); // 使用 Helmet 中间件 // app.use(helmet()); // 创建速率限制器 const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 每个IP在15分钟内最多100个请求 standardHeaders: 'draft-7', // 使用draft-7版本的RateLimit头 legacyHeaders: false // 禁用X-RateLimit-*头 }); app.use('/api/', apiLimiter); // api 接口启用限制 // app.use(cors()); // 启用CORS app.set('trust proxy', 1) //trust first proxy, get ip // 设置视图引擎为EJS app.set('view engine', 'ejs'); // 设置视图目录 app.set('views', [ path.join(__dirname, 'views'), path.join(__dirname, 'views/v2'), ]); /** * Check should compress. */ function shouldCompress(req, res) { if (req.headers['x-no-compression']) { // don't compress responses with this request header return false } // fallback to standard filter function return compression.filter(req, res) } app.use(compression({ filter: shouldCompress })); app.use(cookieParser()); app.use(express.static(config.STATIC_DIR)); app.use(express.static(path.join(__dirname, 'dist'))); app.use(session({ store: new RedisStore({ prefix: 'artsite_sess:' }), cookie: config.cookie, saveUninitialized: false, secret: 'MhxzKhl123.', resave: false, name: config.sessionName || sid, })); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); // 自定义日志中间件 app.use((req, res, next) => { const now = new Date().toISOString(); const ip = req.headers['x-forwarded-for'] || req.ip; console.log(`[${now}] ${ip} ${req.method} ${req.url}`); next(); // 调用 next() 函数,将请求传递给下一个中间件或路由处理程序 }); app.use('/napi/web/auth', require('./routes/napi/web/auth')); app.use('/napi/web/menu', authChecker.checkLogin, require('./routes/napi/web/menu')); app.use('/napi/web/art', authChecker.checkLogin, require('./routes/napi/web/art')); app.use('/napi/web/user', authChecker.checkLogin, require('./routes/napi/web/user')); app.use('/napi/web/role', authChecker.checkLogin, require('./routes/napi/web/role')); app.use('/thumbs/v1', require('./routes/res/thumbs')); app.use('/proxy', require('./routes/proxy')); //v2 app.use('/', require('./routes/v2/index')); // 首页和具体分类合集页 app.use('/coloring-page', require('./routes/v2/detail')) // 详情页 app.use('/coloring-pages', require('./routes/v2/coloring-pages')) // 所有精选合集页 app.use('/coloring-page-gallery', require('./routes/v2/gallery')) // 图库页 app.use('/share', require('./routes/v2/share')) // deeplink share专属页面 ////////////////////////// 合集 ////////////////////////////// app.use('/summer-coloring-pages', require('./routes/v2/coloring-page-collection')) // flower coloring pages 合集 app.use('/flower-coloring-pages', require('./routes/v2/coloring-page-collection')) // flower coloring pages 合集 app.use('/mandala-coloring-pages', require('./routes/v2/coloring-page-collection')) // mandala coloring pages 合集 app.use('/zentangle-coloring-pages', require('./routes/v2/coloring-page-collection')) // zentangle coloring pages 合集 app.use('/zen-coloring-pages', require('./routes/v2/coloring-page-collection')) // zen coloring pages 合集 app.use('/cat-coloring-pages', require('./routes/v2/coloring-page-collection')) // cat coloring pages 合集 app.use('/butterfly-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/architecture-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/simple-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/girl-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/fantasy-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/christmas-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/patterns-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/peacock-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/dragon-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/unicorn-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/food-coloring-pages', require('./routes/v2/coloring-page-collection')) app.use('/video-coloring-pages', require('./routes/v2/video-coloring-page')) app.use('/tips-tricks', require('./routes/v2/tips-tricks')); app.use('/download', require('./routes/res/download')); app.use('/api/comment', require('./routes/v2/comment')); // 评论 app.use('/api/contact', require('./routes/v2/contact')); // 联系信息 app.use('/api/subscribe', require('./routes/v2/subscribe')); // 用户提交邮箱订阅 //v1 app.use('/', require('./routes/index')); // catch 404 and forward to error handler app.use(function (req, res) { // 设置状态码为404 res.status(404); // res.sendFile(path.join(__dirname, '404.html')); res.render('404', { title: '404 Error', description: 'PAGE NOT FOUND' }); }); // error handler app.use(function (err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; console.log("error:" + err + " status: "); // render the error page res.status(err.status || 404); res.render('404', { title: '404 Error', description: 'PAGE NOT FOUND' }); }); // 启动服务器,监听6889端口 const PORT = process.env.PORT || 6889; app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); });