在NodeJS中覆盖res.write

4

我已经玩了一段时间的NodeJS,真的很喜欢它,但是我遇到了一个问题...

我正在尝试创建一个连接模块来拦截http.ServerResponse方法。我的最终目标是允许用户对输出数据应用某种过滤器。例如,他们可以选择在数据发送之前应用压缩或其他操作。

然而,我遇到了一个奇怪的bug...这个方法被调用的频率是正常情况下的两倍。

以下是我的代码:

var http = require('http'), orig;

orig = http.ServerResponse.prototype.write;

function newWrite (chunk) {
    console.log("Called");

    orig.call(this, chunk);
}

http.ServerResponse.prototype.write = newWrite;

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write("Hello");
    res.write(" World");
    res.end();
    console.log("Done");
}).listen(12345);

当我使用浏览器访问时,输出结果为“Hello World”,但控制台却输出了4个“Called”,并且“Done”会重复输出两次。这让我相信我的服务器代码因某种原因被调用了两次。我在this.constructor的newWrite方法中使用console.log,并且在两个实例中都是ServerResponse,所以这没有什么帮助。

我真的很困惑发生了什么。可能发生了什么情况?这并不直接影响输出,但是我可能会向许多客户端同时提供数据压缩后共计几千兆字节的服务,如果所有操作都要做两遍,将对我的服务器施加不必要的压力。

这将成为一个更大的文件服务器的一部分,因此强调不要重复所有操作。

编辑:

如果你想知道,我已经阅读了这篇文章:

在node.js中我可以将http.ServerResponse用作原型吗?

2个回答

6

您的代码没有问题:如果在createServer调用中添加console.log(req.url),您可能会看到它被您的浏览器调用了两次。大多数浏览器会为请求的URL发出一个请求,并且如果在HTML标记中没有指定favicon,则会发出/favicon.ico额外调用。


1
这样就清晰多了!像curl这样的命令行实用程序会这样做吗?我认为不会,因为它们不使用网站图标。我想在生产中我不必担心这个问题,因为我有针对静态文件和查询的不同代码路径。 - beatgammit
不会被 CURL 请求,但浏览器会请求它们。您可以在标记中禁用它们。 - tbranyen

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接