You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IISNode处理带查询参数的GET请求时意外返回相同结果

问题分析与解决方案

核心问题定位

Windows Server 2019 环境下,IIS+IISNode 托管的 Express.js 应用中,相同 URL+查询参数的 GET 请求会在 3-4 次请求后被固定缓存,返回相同响应;而 Windows Server 2012 无此现象,核心原因是两个系统的 IIS/HTTP.sys 缓存策略、IISNode 配置差异导致。


针对性解决步骤

1. 强制禁用响应缓存(最直接的修复)

即使动态生成响应,若未明确禁用缓存,Windows Server 2019 的 IIS/HTTP.sys 会默认缓存看起来是静态内容的响应(如 HTML)。在 Express 路由中添加缓存禁用头:

app.get('/foo', (req, res) => {
  // 明确禁用所有层级的缓存
  res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
  res.setHeader('Pragma', 'no-cache');
  res.setHeader('Expires', '0');
  
  // 生成动态内容
  const timestamp = new Date().toISOString();
  res.send(`<html><body>Current time: ${timestamp}</body></html>`);
});

2. 调整 IIS 输出缓存设置

检查 IIS 站点的输出缓存规则,避免误缓存动态请求:

  • 打开 IIS 管理器,定位目标站点,双击「输出缓存」
  • 删除针对 .html 或所有内容的全局缓存规则;若需保留其他缓存,添加例外规则排除 /foo 路径

3. 修正 IISNode 配置

Windows Server 2019 上的 IISNode 可能存在响应缓冲默认开启的情况,修改 web.config 禁用缓冲:

<handlers>
  <add name="iisnode" path="server.js" verb="*" modules="iisnode" responseBufferLimit="0" />
</handlers>

同时确认 URL 重写规则未误将动态请求识别为静态内容:

<rewrite>
  <rules>
    <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
      <match url="^server.js\/debug[\/]?" />
    </rule>
    <rule name="StaticContent">
      <action type="Rewrite" url="public{REQUEST_URI}" />
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" />
      </conditions>
    </rule>
    <rule name="DynamicContent">
      <conditions>
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
      </conditions>
      <action type="Rewrite" url="server.js" />
    </rule>
  </rules>
</rewrite>

4. 禁用 HTTP.sys 内核级缓存(极端场景)

Windows Server 2019 的 HTTP.sys 内核驱动默认缓存策略更激进,若上述方法无效,可通过注册表禁用:

  • 打开注册表编辑器,定位到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
  • 添加 DWORD 值 UriEnableCache,设置为 0
  • 执行命令重启 HTTP 服务:net stop http && net start http

5. 排查应用层意外缓存

检查 Express 应用是否存在中间件或代码逻辑导致的缓存:

  • 暂时移除 compression 等可能缓存响应的中间件,测试是否恢复正常
  • 确保动态内容变量在路由函数内定义,而非外部全局变量(避免仅初始化一次):
    // 错误示例:全局变量只会生成一次值
    const timestamp = new Date().toISOString();
    app.get('/foo', (req, res) => {
      res.send(`<html><body>Current time: ${timestamp}</body></html>`);
    });
    
    // 正确示例:每次请求生成新值
    app.get('/foo', (req, res) => {
      const timestamp = new Date().toISOString();
      res.send(`<html><body>Current time: ${timestamp}</body></html>`);
    });
    

内容的提问来源于stack exchange,提问作者ciaranj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:07:19