将自定义消息添加到响应标头

时间:2014-04-17 15:18:36

标签: node.js

我正在使用Node.js.

我有一段代码可以很好地返回预期的响应并快速收到响应:

if (req.accepts('json')) {
    res.header('Content-Type', 'application/json');
    res.send(res.locals.items, 200);
}

除了状态200,我想在标题中添加一条消息。因此,我稍微修改了一下代码:

if (req.accepts('json')) {
    res.writeHead( 200, 'my_customizd_message', {'Content-Type' : 'application/json'} );
    res.send(res.locals.items);
}

然后,它抱怨"错误:在发送标题后不能设置标题"。

我尝试了别的东西:

if (req.accepts('json')) {
    res.writeHead( 200, 'my_customizd_message', {'Content-Type' : 'application/json'} );
    res.end();
}

控制台上没有错误消息。但是,没有任何回报。代码永远在运行。我希望有人可以帮助我。非常感谢你。

4 个答案:

答案 0 :(得分:2)

看起来你正在使用Express。重要的是要了解writeHead由节点的核心HTTP库提供,而Express通常会为您管理标头。换句话说,您不应该在Express应用程序中调用writeHead

第一次尝试时出现的错误来自Expess在您拨打writeHead(Express提供的方法)时调用send这一事实。因为您已经手动将标题写入线路,所以Express尝试编写标头失败并引发异常。

你的第二次尝试什么也没有返回,因为你写了标题,然后立即结束响应而不发送任何数据 - 没有错误,因为你没有调用Express方法,但当然客户端什么都看不到。


你遇到的问题是Express的响应方法(如send)设置了各种标题(在某些情况下甚至是响应代码),然后依靠节点的implicit header function来实际编写标题。请注意,writeHead永远不会出现在Express的源代码中。

当您(或在此情况下代表您的Express)开始将数据写入响应(writeend),节点checks以查看是否已发送标头。如果没有,它会为您调用writeHeadmerges任何标头直接传递给该函数,并且标头存储在res._headers中(您通过调用res.setHeader修改的私有属性)。

如果很难完成自定义HTTP状态消息,有几件事情会结合起来:

  • 快速方法(如send)一次设置标题,写入数据和end响应。因此,您无法修改标头或自行使用自定义状态消息致电writeHead

  • 当(当前版本的)节点的HTTP模块写入隐式标头时,它总是写入默认状态消息。没有记录的自定义方式。

那么如何获得自定义状态消息?

  • 可以绕过Express的逻辑并手动响应请求(就像您第二次尝试一样)。但是,当您执行此操作时,您会错过很多有用的功能。只有在你完全知道自己在做什么的情况下才这样做。 (所以不要)

  • 最简单的答案是节点的0.11分支adds res.statusMessage,这样您就可以在调用res.send之前简单地设置所需的消息。不幸的是,0.11不稳定,不应该用于生产。 0.12(具有此功能的下一个稳定版本)将很快出现。当然,这个版本还有几个重大变化(特别是在C ++模块方面),所以你可能无法立即使用它。

  • 节点0.10的权宜之计答案是猴子补丁http.ServerResponse.prototype._implicitHeader。这是一个可能破坏事情的肮脏黑客。自行承担风险。

    http.ServerResponse.prototype._implicitHeader = function() {
        this.writeHead(this.statusCode, this.statusMessage);
    };
    

    当您的应用启动时执行此操作一次。这样您就可以在调用res.statusMessage = 'My Custom Status';之前设置res.send,就像在0.11中一样。

答案 1 :(得分:0)

我以前没用过它,但是这个怎么样?:

if (req.accepts('json')) {
    res.writeHead( 200, {
        'Content-Type' : 'application/json',
        'my_customizd_message':'blah blah'
    });
    res.send(res.locals.items);
}

答案 2 :(得分:0)

现在,我添加了另一行:

res.header('warning' : 'my_customized_message');

它有效。

答案 3 :(得分:0)

根据我刚刚阅读的内容,您可以使用:

res.setHeader(name, value);

setHeader()适用于两个条件:

  1. 您尚未使用writeHead()(即如果已经发送标题,则无法设置标题)
  2. 你还没有寄出一块身体,即。 res.write()或res.end
  3. 如果您需要阅读更多内容,我只是从“ professional node.js ”一书中提取了这些信息,第11页第99页