Express项目部署后访问/tutorials路径报Cannot GET错误 本地运行正常
线上部署后/tutorials路径报Cannot GET的排查与解决
首先明确核心判断:Cannot GET /tutorials/tut1是Express框架原生返回的404响应,说明Nginx已经成功把该请求反向代理到了Node服务,问题和Nginx转发规则无关,全部出在Node侧的运行逻辑与配置上。结合你提到其他静态资源访问正常的前提,按以下顺序排查解决:
1. 修正静态目录配置的路径依赖
你原本写的静态挂载配置:
app.use("/tutorials", express.static('tutorials'));
这里的tutorials是相对路径,解析时会基于Node进程启动时的工作目录查找,而非基于app.js文件的实际位置。
- 本地运行时,你通常在项目根目录直接启动node,路径解析完全正确;但线上用pm2、systemd等进程管理器托管时,如果进程的启动工作目录不是项目根,就会导致express.static找不到对应的tutorials目录,路由匹配失败,返回Cannot GET。
- 修正方法:用绝对路径拼接,完全消除对进程工作目录的依赖:
const path = require('path'); // 将相对路径替换为基于当前文件位置的绝对路径 app.use("/tutorials", express.static(path.join(__dirname, 'tutorials')));
2. 校验动态路由的路径与文件匹配逻辑
你之前写的动态路由存在几处容易在线上触发404的问题:
- 原配置里尝试的
res.sendFile(${tutname}.html,{root:__dirname}),实际查找的文件路径是项目根目录下的tut1.html,并非tutorials子目录下的文件,必然找不到。 - 注意Linux服务器的文件系统是严格大小写敏感的:如果代码里写的目录是
tutorials,但线上实际目录是Tutorials首字母大写,或者实际教程文件名是Tut1.HTML后缀大写,本地开发时因为Windows/macOS默认关闭大小写敏感能正常匹配,线上就会找不到文件触发404。 - 修正后的动态路由写法:
app.get("/tutorials/:tutname", (req, res) => { const tutname = req.params.tutname; // 过滤路径穿越风险,同时取文件名部分避免路径错误 const safeTutName = path.basename(tutname); const filePath = path.join(__dirname, 'tutorials', `${safeTutName}.html`); res.sendFile(filePath, (err) => { // 捕获文件读取错误,避免直接落到默认404逻辑 if (err) res.status(404).send("教程页面不存在"); }); });
3. 快速定位问题的验证步骤
- 跳过Nginx直接测试Node服务:在VPS上执行
curl http://127.0.0.1:<你的Node服务端口>/tutorials/tut1,如果直接请求本地端口也返回Cannot GET,说明问题完全和Nginx无关。 - 检查线上代码版本:确认部署的代码里确实包含tutorials目录、以及对应的路由配置,排除本地改了代码但线上未拉取到最新版本的情况。
- 检查目录权限:确认Node服务的运行用户(如www-data、pm2进程对应的用户)对tutorials目录下的html文件有读取权限,权限不足时sendFile会抛出错误,同样会触发Express的默认Cannot GET响应。
内容的提问来源于stack exchange,提问作者M.KH
相关产品推荐
相关产品推荐

