Express.Router在IIS托管的Node.js应用中无法正常工作
问题背景
本地执行npm start时路由加载正常,但部署到IIS(先后尝试iisnode、反向代理、httpPlatformHandler)后,/api1、/api2路由返回404错误(提示CANNOT GET),仅根路径/和/api-docs可正常访问。
项目结构
node_modules public client.html routes api1.js api2.js server.js web.config
server.js核心代码
// MODULES AND REQUIRES const express = require("express"); const app = express(); const path = require('path'); const swaggerJsDoc = require("swagger-jsdoc"); const swaggerUi = require("swagger-ui-express"); const objectMapper = require('object-mapper'); const cors = require('cors'); // 引入路由 var api1 = require('./routes/api1.js') var api2 = require('./routes/api2.js') // 端口配置 const port = process.env.PORT || 3000; // CORS配置 app.use(cors({ origin: '*' })); // 忽略favicon请求 const ignoreFavicon = (req, res, next) => { if (req.originalUrl.includes('favicon.ico')) { res.status(204).end(); } next(); }; app.use(ignoreFavicon); // 根路由:返回静态页面 app.get('/', (req, res) => { res.sendFile(path.join(__dirname, '/public/client.html')); }); // Swagger文档配置 const options = { customCss: '.swagger-ui .topbar { display: none } .swagger-ui .scheme-container { display: none }' }; const swaggerOptions = { swaggerDefinition: { info: { version: "2.0.0", title: "My App", description: "本页面列出应用可用API并支持测试", contact: { name: "My Name" }, servers: [{"url":"http://localhost:3000", "description": "开发服务器"}] } }, apis: ["./routes/*.js"], }; const swaggerDocs = swaggerJsDoc(swaggerOptions); app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocs, options)); // 挂载路由 app.use('/api1', api1) app.use('/api2', api2) // 启动服务 app.listen(port, () => { console.log(`服务器监听端口 ${port}`); });
当前使用的httpPlatformHandler配置(web.config)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <add name="httppPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" /> </handlers> <httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\logs\node.log" startupTimeLimit="20" processPath="C:\Program Files\nodejs\node.exe" arguments=".\server.js"> <environmentVariables> <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" /> <environmentVariable name="NODE_ENV" value="Production" /> </environmentVariables> </httpPlatform> </system.webServer> </configuration>
现象与排查信息
- 正常访问:
/(加载client.html)、/api-docs(Swagger文档) - 异常:访问
/api1、/api2返回cannot get/404错误 - 反向代理测试:本地
localhost:3000/api1可正常访问,但IIS绑定域名mynode.com/api1仍返回404 - 失败请求跟踪结果:
MODULE_SET_RESPONSE_ERROR_STATUS
ModuleName httpPlatformHandler
Notification EXECUTE_REQUEST_HANDLER
HttpStatus 404
HttpReason Not Found
HttpSubStatus 0
ErrorCode 操作已成功完成。 (0x0)
已尝试操作
- 调整路由路径(如改为
routes/api1)无效 - 疑问:Express.Router是否不支持IIS托管?
解决方案
1. 检查路由文件的Router配置
确保api1.js/api2.js正确使用express.Router(),避免路径重复嵌套:
const express = require('express'); const router = express.Router(); // 正确写法:这里的'/'对应server.js中挂载的'/api1' router.get('/', (req, res) => { res.send('api1响应'); }); // 子路由示例:对应访问路径'/api1/list' router.get('/list', (req, res) => { res.send('api1列表数据'); }); module.exports = router;
注意:如果路由文件内写的是/api1,再通过app.use('/api1', api1)挂载,会导致实际访问路径变为/api1/api1,直接引发404。
2. 确认IIS站点物理路径指向正确
检查IIS站点设置,物理路径必须直接指向包含server.js、routes文件夹的项目根目录,避免路径嵌套导致Node服务无法读取路由文件。
3. 修正httpPlatformHandler的路径配置
修改web.config中httpPlatform的arguments为绝对路径,确保Node能找到server.js:
<httpPlatform stdoutLogEnabled="true" stdoutLogFile=".\logs\node.log" startupTimeLimit="20" processPath="C:\Program Files\nodejs\node.exe" arguments="C:\inetpub\wwwroot\your-project-folder\server.js">
4. 反向代理场景添加URL重写规则
若使用反向代理,需安装IIS的URL重写模块和应用请求路由(ARR),并在web.config中添加重写规则:
<system.webServer> <!-- 原有配置 --> <rewrite> <rules> <rule name="ForwardToNode" stopProcessing="true"> <match url="(.*)" /> <action type="Rewrite" url="http://localhost:3000/{R:1}" /> </rule> </rules> </rewrite> </system.webServer>
5. 查看Node服务日志
检查项目根目录下logs/node.log文件,确认Node服务是否正常启动、是否存在路由文件加载失败等报错信息。
内容的提问来源于stack exchange,提问作者Kode

