【问题标题】:Express redirect is unreliable, is there caching?快速重定向不可靠,是否有缓存?
【发布时间】:2013-12-31 12:00:13
【问题描述】:

我正在使用 nodejs 和 express 将所有 http 请求重定向到 https。通常浏览器会成功重定向到 https,但通常可以输入带有 http(或没有任何协议)的 url,但似乎不会重定向:页面加载但 url 栏保持为 mysite.com,没有 https 或锁定图标。

这在 Chrome 和 IE 中都可能发生。发生这种情况时,Chrome 网络记录器会混合显示 304 和 302 响应。这是否意味着存在某种缓存导致浏览器无法重定向到 https?

   var express = require('express'),
        path = require('path'),
        http = require('http'),
        https = require('https'),
        fs = require ('fs');

    var app = express();

    var options = {
      key: fs.readFileSync('cert/rsa.key'),
      cert: fs.readFileSync('cert/rsa.crt'),
      ca: fs.readFileSync('cert/sub.class1.server.ca.pem')
    };

    function requireHTTPS(req, res, next) {
        if (!req.secure) {
            return res.redirect('https://' + req.get('host') + req.url);
        }
        next();
    }

    app.use(requireHTTPS);

    app.use('/path/html', express.static(rootFolder + 'path/html'));
    app.use('/path/fonts', express.static(rootFolder + 'path/fonts'));

    app.all('*', function (req, res) {
        res.sendfile('index.html', { root: rootFolder + 'path/' });
    })

    https.createServer(options, app).listen(443);
    http.createServer(app).listen(80);

编辑 - 复制技巧

我正在为 express 使用推荐的 https 重定向方法,所以我怀疑许多网站在没有意识到的情况下遇到了这个问题。对于 W7 上的 Chrome,我总是在第一次访问或使用 url 自动完成或多功能框下拉菜单时看到正确的重定向。但是,如果我输入 url 或手动编辑自动完成,那么我可以可靠地看到失败的重定向:

  1. 删除 chrome 浏览器缓存

  2. 输入您的网址http://_mysite.com 并回车 => 正确重定向到https://_mysite.com

  3. 创建一个新选项卡,输入您的网址,直到它自动完成并按 Enter => 正确重定向到https://_mysite.com

  4. 创建一个新选项卡,如 3。但在按 Enter 之前,通过删除最后一个字符并重新键入来编辑自动完成,按 Enter => 页面呈现,但 url 保持在 http://_mysite.com 没有锁定符号。

服务器日志显示未获取根静态页面,仅获取页面内容的某些部分。尽管浏览器没有报告这一点,但对页面内容的所有获取请求都是 https。

【问题讨论】:

标签: javascript redirect express browser-cache


【解决方案1】:

当你这样做时:

return res.redirect('https://' + req.get('host') + req.url);

Express 将返回 302。

但是,由于缓存(正如您所怀疑的那样),该代码可能无法执行。

如果您的浏览器之前缓存了该页面,那么浏览器将发送一个有条件的 HTTP 请求,基本上是告诉 Express,“将页面发送给我,但前提是它已更改。”如果页面没有变化,Express 会发送一个304 Not Modified

清除浏览器的缓存并重试,或对页面进行一些小修改。

在后台,Express 使用node-fresh 来决定是否发送304 响应。逻辑相当简单,可以看到here。它检查的因素之一是页面的 ETag(页面正文的哈希)。因此,对页面的任何微小更改都会迫使您的浏览器刷新它。或者,如果你想强制浏览器每次都获取一个新的页面副本,你可以设置Cache-Control: no-cache

您也可以禁用 ETag:

app.disable('etag')

当然,这可能会导致更多流量,而条件请求和304 响应旨在减少。

【讨论】:

  • AFAIK,仅当响应会生成 200 响应时才应检查 ETag,而在重定向的情况下则不是这样。所以要么 Express 有问题,要么发生了其他事情。
  • 好点。肯定是 Express 做的,所以它可以被认为是一个错误。不过我不知道如何修复它,因为您希望在请求处理程序中尽早发生有条件的事情。
  • 你能重现它吗?因为我不能 :) 我也看不出它是如何工作的,因为当中间件生成 302 时,没有任何东西可以计算 ETag。
  • 谢谢你的回答,虽然我很困惑!
  • 告诉我你的问题!
【解决方案2】:

这是试图回答我自己的问题。通过强制 307 响应,我看到了没有缓存的可靠重定向。但是我不确定这是多么“正确”,以及是否可以放心地使用它而不会破坏未来的浏览器版本。

function requireHTTPS(req, res, next) {
    if (!req.secure) {
        return res.redirect(307, 'https://' + req.get('host') + req.url);
    }
    next();
}

【讨论】:

    【解决方案3】:

    这是我用来强制 HTTPS 的。

    requireHTTPS = function(req, res, next){
      if (req.secure)  return next();
      res.redirect("https://" + req.headers.host + req.url);  
    }
    

    【讨论】:

      猜你喜欢
      • 2013-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      相关资源
      最近更新 更多