You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,需手动完成连接。

具体修改步骤

  1. 修正connect-redis导入方式
    将原导入代码:
const RedisStore = require('connect-redis')(session);

改为:

const RedisStore = require('connect-redis').default(session);
  1. 添加Redis客户端连接逻辑
    在创建客户端后添加异步连接代码:
(async () => {
  try {
    await client.connect();
    console.log('Redis client connected successfully');
  } catch (err) {
    console.error('Failed to connect to Redis:', err);
  }
})();
  1. 移除动态加载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;
  1. 验证依赖版本兼容性
    确保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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:07:05