Node.js使用Express框架无法隐藏URL中文件扩展名问题求助
问题原因
你的代码存在3个核心错误,导致运行不符合预期:
- 中间件优先级错误:
express.static静态资源中间件定义在自定义路由之前,优先级更高,请求会先匹配静态资源。只有无对应静态文件时才会进入自定义路由,同时也会直接暴露带.json后缀的文件访问路径。 - 文件路径拼接错误:自定义路由中直接使用
name+'.json'作为路径,没有拼接data目录路径,fs.open默认从项目根目录查找文件,自然找不到data目录下的users.json,返回404。 - 文件读取逻辑错误:
fs.open拿到的是文件描述符(数字类型),直接调用res.json(fd)只会返回数字,不会返回JSON文件内容;同时你没有通过fs调用close方法,会直接报错。
修复方案
步骤1:调整中间件顺序/移除不必要的静态中间件
如果你不需要对外直接暴露带.json后缀的访问路径,可以直接删除app.use('/api', express.static(...))这行代码;如果需要保留,就把它放到自定义路由的后面。
步骤2:修正文件路径与读取逻辑
直接使用express内置的res.sendFile方法简化逻辑,同时增加路径安全校验,避免路径穿越漏洞。
修复后完整代码
const express = require('express'); const path = require('path'); const fs = require('fs'); const app = express(); const PORT = 3000; // 可选:如果不需要暴露带后缀的访问,可删除下面这行静态中间件配置 // app.use('/api', express.static(path.join(__dirname,'data')) ); app.get('/api/:name',(req,res) => { let {name} = req.params; // 拼接正确的文件路径 const filePath = path.join(__dirname, 'data', `${name}.json`); // 校验文件是否在data目录内,防止路径穿越攻击 if (!filePath.startsWith(path.join(__dirname, 'data'))) { return res.status(403).end('非法访问'); } // 直接发送文件,express会自动处理文件存在性校验、响应头设置 res.sendFile(filePath, (err) => { if (err) { if (err.code === 'ENOENT') { return res.status(404).end(`404 ${name}.json不存在`); } res.status(500).end('服务器错误'); } }); }); // 如果保留了静态中间件,要放在路由定义之后 // app.use('/api', express.static(path.join(__dirname,'data')) ); app.listen(PORT, () => { console.log(`服务运行在 http://localhost:${PORT}`); });
修改后访问localhost:3000/api/users即可正常返回users.json的内容,同时默认禁止带.json后缀的访问,如果需要保留带后缀的访问,放开对应静态中间件的注释即可。
内容的提问来源于stack exchange,提问作者user2408962
相关产品推荐
相关产品推荐

