Nodejs express 304/302 访问超时

Nodejs express 304/302 访问超时

express版本:express 3.4.8和express 4.9.5 环境:linux 64位 操作步骤:

  1. 安装express命令 #npm install -g express-generator;

  2. 建立网站基本结构 #express --ejs blog;

  3. 安装模块 #npm install;

  4. 将ip和port绑定到一个域名url。 访问地址url,页面正常加载,前端页面截图: normal.jpg 后台打印的日志截图: h200.png

  5. 刷新页面 页面一直加载不出来,直到超时,前端网页截图: ti.png 后台打印的日志截图: 304.png 此时后台一直卡在304状态,没有发送应答给浏览器,然后浏览器过一段时间显示超时。

  6. 禁止掉etag后不会出现此问题(每次请求都返回200,不再是304)。 app.disable(‘etag’);

  7. 禁止掉etag后,只要express应答出现304或者重定向(redirect)302都会出现上述问题。

    哪位大神遇到过这个问题,求解答。

  • linux服务器的问题?
  • express的配置问题?
  • express本来就存在这个问题?

5 回复

Node.js Express 304/302 访问超时

环境与版本

  • Express 版本: 3.4.8 和 4.9.5
  • 操作系统: Linux 64位

操作步骤

  1. 安装 Express

    npm install -g express-generator
    
  2. 创建项目结构

    express --ejs blog
    cd blog
    npm install
    
  3. 启动应用

    node app.js
    

    访问 http://your-domain:3000,页面可以正常加载。

    • 前端页面截图: 正常加载

    • 后台日志截图: HTTP 200

  4. 刷新页面 页面长时间无响应,最终超时。

    • 前端页面截图: 超时

    • 后台日志截图: HTTP 304

问题分析

  • 304 Not Modified:

    • 当客户端请求资源时,如果资源未修改,服务器会返回304状态码,这表示客户端的缓存有效。然而,在某些情况下,这种机制会导致页面长时间无响应。
  • 302 Found:

    • 重定向302也会导致同样的问题,客户端不断尝试新的URL,而服务器端没有及时响应。

解决方案

  1. 禁用 ETag

    • ETag 是一种用于验证资源是否改变的机制,禁用它可以避免304状态码。
    app.disable('etag');
    
  2. 处理重定向

    • 如果需要重定向,确保在重定向之前进行适当的处理,例如检查某些条件。
    app.get('/some-route', function(req, res) {
        // 检查条件
        if (condition) {
            res.redirect('/new-url');
        } else {
            res.send('OK');
        }
    });
    

可能的原因

  • Linux 服务器问题: 可能是服务器配置或网络问题。
  • Express 配置问题: ETag 或者重定向配置不当。
  • Express 本身问题: 在某些版本中可能存在已知问题。

希望这些信息能够帮助你解决问题。如果你有更多细节或错误日志,可以进一步排查。


关注一下

好难的感觉…

重现了一下,无论是Firefox还是Chrome直接访问http://ip_address:port都没问题。你是用域名访问的,直接用IP地址访问,检查是否还出现这个问题。

下面是测试用到的设置:

  • Ubuntu 14.04 64bit
  • node.js 0.10.29
  • npm 1.4.14
  • express 4.9.5

根据你的描述,该问题可能与Express框架中的缓存机制有关。304 Not Modified 状态码表示资源未被修改,通常用于HTTP缓存。当客户端请求资源且缓存有效时,服务器会返回 304 状态码,并让客户端从本地缓存中读取数据。

解释

  • 问题根源:当你设置 etag 后,Express会自动添加一个 etag 头信息到响应中。如果客户端请求同一个资源时,它会带上一个 if-none-match 请求头。如果服务器发现资源未被修改,则返回 304 状态码。此时,客户端应该从缓存中获取资源,而不是等待服务器重新发送资源。

  • 实际现象:你在禁用了 etag 后,问题消失。说明问题确实与 etag 有关。如果你希望避免 304302 状态码导致的访问超时问题,可以考虑以下几种方法:

方法一:禁用 etag

const express = require('express');
const app = express();

// 禁用 etag
app.disable('etag');

// 其他中间件和路由配置

方法二:确保路由处理函数能够正确处理 304 状态

确保你的路由处理函数能快速返回,即使返回 304 状态码。

app.get('/example', (req, res) => {
    // 假设 'data' 是一个资源对象
    const data = getData(req.params.id);
    
    if (data.isModifiedSince(req)) {
        res.status(200).send(data.content);
    } else {
        res.status(304).end();
    }
});

方法三:检查客户端的 if-modified-sinceif-none-match 请求头

确保客户端正确设置了这些请求头,以便服务器能够正确判断是否需要返回 304 状态码。

结论

该问题可能是由于客户端未能正确处理 304 状态码,或者Express的 etag 配置导致的问题。通过禁用 etag 或者确保路由处理函数能够快速返回,可以解决该问题。如果以上方法都不能解决问题,建议进一步排查客户端和服务器之间的交互细节。

回到顶部