From 7e203d9a2783408159f325b0f60448e761cb1db6 Mon Sep 17 00:00:00 2001 From: canglan Date: Mon, 17 Aug 2026 00:01:36 +0800 Subject: [PATCH] fix: 404 interface not found after login - business routes on dedicated router so dynamic loading precedes catch-all --- backend/server.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/backend/server.js b/backend/server.js index 81d9ec3..86e6072 100644 --- a/backend/server.js +++ b/backend/server.js @@ -100,32 +100,37 @@ app.use('/js', express.static(path.join(PUBLIC_DIR, 'js'), staticOpts)); const installRoutes = require('./routes/install'); app.use('/api/install', installRoutes); +// 业务路由挂在独立 Router 上: 动态添加的路由在 Router 内部按序匹配, +// 不会被注册在 Router 之后的 404 兜底抢先(修复安装后"接口不存在") +const businessRouter = express.Router(); +app.use('/api', businessRouter); + let businessLoaded = false; function loadBusinessRoutes() { if (businessLoaded) return; businessLoaded = true; const authRoutes = require('./routes/auth'); - app.use('/api/auth/login', methodGuard(['POST']), loginLimiter); - app.use('/api/auth/register', methodGuard(['POST']), registerLimiter); - app.use('/api/auth', authRoutes); + businessRouter.use('/auth/login', methodGuard(['POST']), loginLimiter); + businessRouter.use('/auth/register', methodGuard(['POST']), registerLimiter); + businessRouter.use('/auth', authRoutes); - app.use('/api/captcha', methodGuard(['GET']), captchaLimiter, require('./routes/captcha')); + businessRouter.use('/captcha', methodGuard(['GET']), captchaLimiter, require('./routes/captcha')); - app.use('/api/tickets', methodGuard(['GET','POST','PUT']), ticketLimiter, require('./routes/tickets')); - app.use('/api/reports', methodGuard(['GET','POST','PUT']), ticketLimiter, require('./routes/tickets')); + businessRouter.use('/tickets', methodGuard(['GET','POST','PUT']), ticketLimiter, require('./routes/tickets')); + businessRouter.use('/reports', methodGuard(['GET','POST','PUT']), ticketLimiter, require('./routes/tickets')); - app.use('/api/users', methodGuard(['GET','POST','PUT']), generalLimiter, require('./routes/users')); - app.use('/api/settings', methodGuard(['GET','PUT']), generalLimiter, require('./routes/settings')); - app.use('/api/export', methodGuard(['GET']), generalLimiter, require('./routes/export')); - app.use('/api/uploads', methodGuard(['GET']), generalLimiter, require('./routes/uploads')); - app.use('/api/notifications', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/notifications')); - app.use('/api/polls', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/polls')); - app.use('/api/features', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/features')); - app.use('/api/bans', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/bans')); - app.use('/api/external', require('./routes/external')); + businessRouter.use('/users', methodGuard(['GET','POST','PUT']), generalLimiter, require('./routes/users')); + businessRouter.use('/settings', methodGuard(['GET','PUT']), generalLimiter, require('./routes/settings')); + businessRouter.use('/export', methodGuard(['GET']), generalLimiter, require('./routes/export')); + businessRouter.use('/uploads', methodGuard(['GET']), generalLimiter, require('./routes/uploads')); + businessRouter.use('/notifications', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/notifications')); + businessRouter.use('/polls', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/polls')); + businessRouter.use('/features', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/features')); + businessRouter.use('/bans', methodGuard(['GET','POST','PUT','DELETE']), generalLimiter, require('./routes/bans')); + businessRouter.use('/external', require('./routes/external')); - app.get('/api/verify', (req, res) => res.redirect(`/#/verify?token=${req.query.token}`)); + businessRouter.get('/verify', (req, res) => res.redirect(`/#/verify?token=${req.query.token}`)); } if (isInstalled()) loadBusinessRoutes();