【问题标题】:On Heroku, why can't I see all the request headers with nodejs?在 Heroku 上,为什么我看不到 nodejs 的所有请求标头?
【发布时间】:2013-05-03 09:46:26
【问题描述】:

我正在尝试控制我的 nodejs 应用程序中的静态文件缓存标头,如https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers#conditional-requests 所述。我想使用“etag”/“if-none-match”方法。

问题是我的请求的“if-none-match”标头在 Heroku 上始终未定义。它在我的开发服务器上运行良好。

这是我的 fs.readFile 调用:

fs.readFile(SERVERDIR+'client/'+file, function(err, data) {
    if(err) {
        console.log(currTime() + ' [STATIC] ... ' + err);
        if(err.code === "ENOENT") {      // file is simply missing
            resNotFound(res,'file not found',err);
        } else {                        // other error; could be EACCES or anything
            resInternalError(res,'internal server error',err);
        }
    }
    else {
        fs.stat(SERVERDIR+'client/'+file, function (err, stat) {
            if (err) {
                resInternalError(res,'internal server error',err);
            }
            else {
                var etag = stat.size + '-' + Date.parse(stat.mtime);
                res.setHeader('Last-Modified', stat.mtime);
                if(LOGSTATIC) { console.log(currTime() + ' [STATIC] ... etag : ' + etag); }
                if(LOGSTATIC) { console.log(currTime() + ' [STATIC] ... req.if-none-match : ' + req.headers['if-none-match']); }
                if(LOGSTATIC) { console.log(req.headers); }

                if (req.headers['if-none-match'] === etag) {
                    res.statusCode = 304;
                    res.end();
                }
                else {
                    res.setHeader('Content-Length', data.length);
                    res.setHeader('ETag', etag);
                    res.statusCode = 200;
                    res.end(data);
                }
            }
        });
    }
});

这里是单个文件请求的 heroku 日志:

2013-05-03T10:32:05.461070+00:00 heroku[router]: at=info method=GET path=/css/common.css host=www.chess-hub.net fwd="193.252.157.50" dyno=web.1 connect=0ms service=5ms status=200 bytes=792
2013-05-03T10:32:05.455619+00:00 app[web.1]: 10:32 [STATIC] ... serving client//css/common.css
2013-05-03T10:32:05.457981+00:00 app[web.1]: { 'x-request-start': '1367577125454',
2013-05-03T10:32:05.457981+00:00 app[web.1]:   'x-forwarded-port': '80',
2013-05-03T10:32:05.455443+00:00 app[web.1]: 10:32 [STATIC] client file request
2013-05-03T10:32:05.457981+00:00 app[web.1]:   'x-forwarded-proto': 'http',
2013-05-03T10:32:05.456127+00:00 app[web.1]: 10:32 [STATIC] ... req if-none-match : undefined
2013-05-03T10:32:05.457981+00:00 app[web.1]:   cookie: 'BCSI-CS-56C420186ECC3F22=2',
2013-05-03T10:32:05.457981+00:00 app[web.1]:   dnt: '1',
2013-05-03T10:32:05.457981+00:00 app[web.1]:   'cache-control': 'max-age=0',
2013-05-03T10:32:05.457981+00:00 app[web.1]:   'x-forwarded-for': '193.252.157.50',
2013-05-03T10:32:05.456046+00:00 app[web.1]: 10:32 [STATIC] ... etag : 792-1367572582000
2013-05-03T10:32:05.457981+00:00 app[web.1]:   host: 'www.chess-hub.net',
2013-05-03T10:32:05.458231+00:00 app[web.1]:   accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }
2013-05-03T10:32:05.457981+00:00 app[web.1]:   'user-agent': 'Mozilla/5.0 (Windows NT 5.1; rv:19.0) Gecko/20100101 Firefox/19.0',
2013-05-03T10:32:05.458231+00:00 app[web.1]:   'accept-language': 'fr-FR,en-us;q=0.5',
2013-05-03T10:32:05.457981+00:00 app[web.1]:   connection: 'close',
2013-05-03T10:32:05.458231+00:00 app[web.1]:   'accept-encoding': 'gzip, deflate',

...就是这样。不确定 heroku 在保存日志时如何截断输出。

感谢您的帮助。

编辑:看起来问题与我通过代理连接的事实有关。当我跳过它时,heroku 日志正确显示“if-none-match”标头,并且我的应用程序返回 http/304 代码。我的代理在请求中添加了一个巨大的“代理授权”令牌,这可能是标题中的长度限制吗?

【问题讨论】:

  • 在原帖中添加heroku日志的输出。

标签: node.js heroku http-headers httprequest


【解决方案1】:

有两个问题可能会导致您观察到的行为:

  • EtagLast-Modifed 是多余的标头,您应该只使用两者之一。因为您同时返回两者,所以浏览器可能会发送if-modified-since 而不是if-none-match。在您的情况下,Last-Modified 标头似乎比 Etags 更合适。
  • 您没有明确将响应配置为可缓存,因此浏览器可能决定根本不缓存。尝试返回 Cache-Control:public, max-age=2592000, must-revalidateExpires(但不能同时返回)

另请参阅 this guide 以获得对缓存控制标头的详细说明。

像 firebug 这样的工具将极大地帮助您检查浏览器发送和接收的标头。

【讨论】:

  • 感谢您的建议。使用 FF 控制台,我可以看到请求和响应。 “if-none-match”包含之前发送的 etag 值,但我在 req.headers 数组中看不到这个值。如果在我的开发服务器上工作。
  • @SylvainYVON 您的浏览器使用代理服务器吗?
  • 这正是我刚刚意识到的(见我的编辑)。这是一个已知问题吗?
  • @SylvainYVON 代理可以执行各种请求规范化,并且可以自己进行缓存。尝试使用正确的方式通过 etag 验证启用缓存,代理应该正确处理这个问题。即使没有您当前返回的代理标头,也无法在某些浏览器上使用。
  • 谢谢,除了我的 eTag 之外,发送一个正确的缓存控制标头似乎可以解决问题。
猜你喜欢
  • 1970-01-01
  • 2017-08-24
  • 2021-08-10
  • 2017-01-28
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
相关资源
最近更新 更多