Express服务端设置路由参数重定向报404如何解决
问题成因
- 核心错误是GET路由的注册逻辑完全写错了:你在服务启动阶段就执行了
app.get('/user/' + userId, ...),此时全局声明的userId是undefined,最终服务实际注册的有效路由只有/user/undefined。Express的路由是服务启动时就固定注册好的,不会因为后续请求里修改了全局userId变量就自动新增路由,你重定向到/user/10这类路径时根本没有匹配的路由处理,自然返回404。 - 额外的逻辑隐患:你用全局变量存单次请求拿到的
userId,在并发请求场景下会被不同用户的请求反复覆盖,直接导致用户串号、数据错乱;另外数据库查询没有做错误处理、用map遍历结果赋值的写法也会在查询结果为空/多条时拿到异常的userId值。
正确实现方式
Express原生支持动态路由参数,不需要为每个用户单独拼接注册路由,用:参数名的形式定义路径中的动态段即可,所有匹配规则的请求都会进入这个路由处理函数,动态参数可以通过req.params直接获取。
修正后的代码如下:
// 删掉全局声明的const userId,禁止用全局变量存储单请求的用户数据 app.post('/userSignUp', (req, resp, next) => { const HashQuery = { text: 'select * from users where session_id = $1', values: [req.cookies.hash_from_its_an_app] } client.query(HashQuery, (err, res) => { // 先处理数据库查询错误,避免后续逻辑拿到空值 if (err) { return next(err); } // 校验查询结果,不存在对应用户直接返回错误 if (!res.rows.length) { return resp.status(400).send('身份校验失败,请重新登录'); } // 从查询结果第一条取用户ID,不需要map遍历 const userId = res.rows[0].user_id; // 原有重定向逻辑不需要修改 resp.redirect('/user/'+ userId); }) }) // 注册动态路由,:userId是路径动态参数,匹配所有/user/xxx格式的GET请求 app.get('/user/:userId', (req, res) => { // 从路径中取到实际的用户ID,例如访问/user/10时,req.params.userId值为'10' const targetUserId = req.params.userId; // 可在此处追加权限校验,判断当前访问者是否有权限查看该用户页面 res.render('index', { userId: targetUserId }); });
注意事项
- 所有和单次请求绑定的数据都要存在请求作用域的变量里(比如路由回调里声明的
const userId、req对象上挂载的属性),绝对不要用全局变量存储,否则并发场景下必然出现数据错乱 - 所有异步操作(数据库查询、接口请求等)都要先处理错误分支,不要默认操作一定成功
- 动态路径场景直接用框架提供的路由参数能力即可,不需要动态拼接注册路由,这类路由在服务启动时注册一次规则就可以处理所有符合规则的请求
内容的提问来源于stack exchange,提问作者Deke
相关产品推荐
相关产品推荐

