Azure Node.js后端Webapp connect-redis模块500错误修复咨询
问题描述
在Microsoft Azure上部署了ReactJS前端Web应用与Node.js后端Web应用,前端登录时会向后端API发送POST请求,经排查问题出在connect-redis模块。Azure日志流显示错误发生在定义RedisStore的第6行:
Application has thrown an uncaught exception and is terminated:TypeError: require(...) is not a functionat Object.
曾尝试临时方案(先将session设为null,用户登录后再修改),该方案能让登录POST请求正常,但仪表盘的GET/POST数据请求均无法工作。确认问题出在后端的api.js文件中(后端包含api.js、server.js和database.js,前端包含Login.js,登录后跳转至dashboard.js)。
原始api.js代码
const express = require('express'); const router = express.Router(); const db = require('./database'); const session = require('express-session'); const redis = require('redis'); const RedisStore = require('connect-redis')(session); // Redis client configuration const client = redis.createClient({ url: '<redacted for security>', port: 6380, password: '<redacted for security>', tls: { rejectUnauthorized: false } }); client.on('error', (err) => { console.log('Redis error: ', err); }); // Middleware to check if a user is authenticated function checkAuthenticated(req, res, next) { if (req.session && req.session.username) { next(); } else { // User is not authenticated, respond with 401 status res.status(401).json({ message: 'User not logged in.' }); } } // Setup session middleware router.use(session({ store: new RedisStore({ client: client }), secret: 'Your_Secret_Key', resave: false, saveUninitialized: false })); router.post('/login', async (req, res) => { const { username, password } = req.body; const user = await db.getUser(username, password); if(user) { req.session.username = username; res.status(200).json({ message: 'User logged in successfully.' }); } else { res.status(401).json({ message: 'Invalid username or password.' }); } }); router.get('/get-promises', checkAuthenticated, async (req, res) => { const senusername = req.session.username; try { const promises = await db.getAllPromises(senusername); // pass senusername as parameter return res.status(200).json(promises); } catch (err) { return res.status(500).json({ error: 'Error retrieving promises.' }); } }); router.post('/add-promise', checkAuthenticated, async (req, res) => { const { promise, recusername, sentAt } = req.body; const senusername = req.session.username; const status = 'active'; try { await db.addPromise(promise, status, recusername, senusername, sentAt); return res.status(200).json({ message: 'Promise added successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error adding the promise.' }); } }); router.put('/update-promise/:id', checkAuthenticated, async (req, res) => { const { id } = req.params; const { status } = req.body; try { await db.updatePromiseStatus(id, status); return res.status(200).json({ message: 'Promise status updated successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error updating the promise status.' }); } }); module.exports = router;
尝试修改后的代码(出现"memorystore不是有效方法"错误)
const express = require('express'); const router = express.Router(); const db = require('./database'); const session = require('express-session'); const redis = require('redis'); let RedisStore = null; // Redis client configuration const client = redis.createClient({ host: '<redacted for security>', port: 6380, password: '<redacted for security>', tls: { rejectUnauthorized: false } }); client.on('error', (err) => { console.log('Redis error: ', err); }); // Middleware to check if a user is authenticated function checkAuthenticated(req, res, next) { if (req.session && req.session.username) { next(); } else { // User is not authenticated, respond with 401 status res.status(401).json({ message: 'User not logged in.' }); } } // Setup session middleware router.use((req, res, next) => { if (req.session) { RedisStore = require('connect-redis')(session); } session({ store: RedisStore ? new RedisStore({ client: client }) : undefined, secret: 'Your_Secret_Key', resave: false, saveUninitialized: false })(req, res, next); }); router.post('/login', async (req, res) => { const { username, password } = req.body; const user = await db.getUser(username, password); if(user) { req.session.username = username; res.status(200).json({ message: 'User logged in successfully.' }); } else { res.status(401).json({ message: 'Invalid username or password.' }); } }); router.get('/get-promises', checkAuthenticated, async (req, res) => { const senusername = req.session.username; try { const promises = await db.getAllPromises(senusername); // pass senusername as parameter return res.status(200).json(promises); } catch (err) { return res.status(500).json({ error: 'Error retrieving promises.' }); } }); router.post('/add-promise', checkAuthenticated, async (req, res) => { const { promise, recusername, sentAt } = req.body; const senusername = req.session.username; const status = 'active'; try { await db.addPromise(promise, status, recusername, senusername, sentAt); return res.status(200).json({ message: 'Promise added successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error adding the promise.' }); } }); router.put('/update-promise/:id', checkAuthenticated, async (req, res) => { const { id } = req.params; const { status } = req.body; try { await db.updatePromiseStatus(id, status); return res.status(200).json({ message: 'Promise status updated successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error updating the promise status.' }); } }); module.exports = router;
解决方案
错误TypeError: require(...) is not a function源于connect-redis版本兼容性问题:
connect-redis@6+不再支持直接传入session的调用方式,需调整导入逻辑;redis@4+的createClient返回Promise,需手动完成连接。
具体修改步骤
- 修正
connect-redis导入方式
将原导入代码:
const RedisStore = require('connect-redis')(session);
改为:
const RedisStore = require('connect-redis').default(session);
- 添加Redis客户端连接逻辑
在创建客户端后添加异步连接代码:
(async () => { try { await client.connect(); console.log('Redis client connected successfully'); } catch (err) { console.error('Failed to connect to Redis:', err); } })();
- 移除动态加载
connect-redis的错误逻辑
直接在文件顶部完成导入,保持会话中间件配置的稳定性。
修改后的完整api.js代码
const express = require('express'); const router = express.Router(); const db = require('./database'); const session = require('express-session'); const redis = require('redis'); const RedisStore = require('connect-redis').default(session); // Redis client configuration const client = redis.createClient({ url: '<redacted for security>', port: 6380, password: '<redacted for security>', tls: { rejectUnauthorized: false } }); // 连接Redis客户端 (async () => { try { await client.connect(); console.log('Redis client connected successfully'); } catch (err) { console.error('Failed to connect to Redis:', err); } })(); client.on('error', (err) => { console.log('Redis error: ', err); }); // Middleware to check if a user is authenticated function checkAuthenticated(req, res, next) { if (req.session && req.session.username) { next(); } else { res.status(401).json({ message: 'User not logged in.' }); } } // Setup session middleware router.use(session({ store: new RedisStore({ client: client }), secret: 'Your_Secret_Key', resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', // Azure生产环境开启secure httpOnly: true, maxAge: 24 * 60 * 60 * 1000 // 1天有效期 } })); router.post('/login', async (req, res) => { const { username, password } = req.body; const user = await db.getUser(username, password); if(user) { req.session.username = username; res.status(200).json({ message: 'User logged in successfully.' }); } else { res.status(401).json({ message: 'Invalid username or password.' }); } }); router.get('/get-promises', checkAuthenticated, async (req, res) => { const senusername = req.session.username; try { const promises = await db.getAllPromises(senusername); return res.status(200).json(promises); } catch (err) { return res.status(500).json({ error: 'Error retrieving promises.' }); } }); router.post('/add-promise', checkAuthenticated, async (req, res) => { const { promise, recusername, sentAt } = req.body; const senusername = req.session.username; const status = 'active'; try { await db.addPromise(promise, status, recusername, senusername, sentAt); return res.status(200).json({ message: 'Promise added successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error adding the promise.' }); } }); router.put('/update-promise/:id', checkAuthenticated, async (req, res) => { const { id } = req.params; const { status } = req.body; try { await db.updatePromiseStatus(id, status); return res.status(200).json({ message: 'Promise status updated successfully.' }); } catch (err) { return res.status(500).json({ error: 'Error updating the promise status.' }); } }); module.exports = router;
- 验证依赖版本兼容性
确保package.json中的依赖版本匹配:
"dependencies": { "express": "^4.18.2", "express-session": "^1.17.3", "redis": "^4.6.7", "connect-redis": "^7.1.0" }
执行npm install更新依赖后重新部署应用。
内容的提问来源于stack exchange,提问作者Josh Locke
相关产品推荐
相关产品推荐

