Express框架中单个请求为何会同时命中多个路由?
现象说明
这不是Express的新增功能特性,触发额外日志打印的核心原因是浏览器的默认请求行为,和Express本身的路由匹配规则无关。
访问/路由时能正常返回目标文件,说明/路由的匹配和执行完全正常,触发/*路由打印的是浏览器自动发起的额外隐式请求:
- 所有主流浏览器在访问站点根路径时,都会默认自动发起一个
/favicon.ico的GET请求,用来获取站点标签页展示的图标文件 - 这个请求路径刚好匹配你定义的
/*通配符路由,所以会执行路由内部的console.log("30hrs")逻辑 - 你当前写的
/*路由没有返回任何响应、也没有调用next()移交控制权,所以匹配到该路由的请求会处于挂起状态,只是因为没有其他逻辑,你只会观察到控制台打印的日志
验证方式
在/*路由的打印逻辑前增加路径打印代码:
app.get('/*', (req, res) => { console.log(req.path, "30hrs") });
重新访问/路由后,你会在控制台看到对应/favicon.ico路径的打印记录,这就是你观察到的额外触发来源。
修复方式
- 优先使用Express内置的
express.static中间件托管静态资源(包括favicon图标、html文件、静态脚本样式等),这类静态资源请求会被中间件直接处理,不会走到后续的业务路由 - 给
/*兜底路由补充明确的响应逻辑,不要让请求挂起;如果不需要处理favicon类的默认请求,可以直接在路由内返回204无内容状态:
// 提前托管静态资源 app.use(express.static(__dirname + "/files")); app.get('/', (req, res) => { if(JSON.stringify(req.cookies)=="{}"){ res.cookie('number',1, { maxAge: 900000, httpOnly: true }); } else{ res.cookie('number',Number(req.cookies.number)+1, { maxAge: 900000, httpOnly: true }); } res.sendFile('main.html', {root: __dirname+"/files/html"}); }); app.get('/*', (req, res) => { // 过滤favicon默认请求 if(req.path === '/favicon.ico') return res.status(204).end(); console.log("30hrs") // 补充兜底响应 res.status(404).send("Page not found"); });
- 如果不需要通配路由做全局兜底,直接移除
/*路由即可避免无意义的匹配。
内容的提问来源于stack exchange,提问作者Symney Cameron
相关产品推荐
相关产品推荐

