如何在node / express中发送自定义http状态消息?


89

我的node.js应用程序的建模类似于express / examples / mvc应用程序。

在控制器操作中,我想通过自定义http消息吐出HTTP 400状态。默认情况下,http状态消息为“错误请求”:

HTTP/1.1 400 Bad Request

但是我想发送

HTTP/1.1 400 Current password does not match

我尝试了各种方法,但是没有一种方法将http状态消息设置为我的自定义消息。

我当前的解决方案控制器功能如下所示:

exports.check = function( req, res) {
  if( req.param( 'val')!=='testme') {
    res.writeHead( 400, 'Current password does not match', {'content-type' : 'text/plain'});
    res.end( 'Current value does not match');

    return;
  } 
  // ...
}

一切正常,但是……似乎不是正确的方法。

有没有更好的方法来使用express设置http状态消息?


4
好吧,这似乎是唯一的解决方法。但是我不会建议这样的事情,HTTP 1.1规范出于某些很好的原因将其错误描述标准化了。我认为发送带有自定义说明的知名状态代码是一种不好的做法,但这取决于您。
schaermu 2013年

嗯-也许那是真的。另一方面,我假设浏览器仅检查状态码,而不检查人类可读的http状态消息。我认为使用http状态消息来传输具体的(即非默认)错误消息(如果可用)是个好主意。加上其易于抓取,使用客户端Java脚本(使用jQuery你可以做“jqXHR.statusText”获取用于显示的目的)中的错误
lgersman

4
这与兼容性或潜在的浏览器问题无关,这只是一种不好的做法;)如果要显示错误消息,请将其作为正文发送,这是预期的目的。
schaermu 2013年

6
特定的错误描述不属于规范的一部分。RCF-2616特别指出:“为HTTP / 1.1定义的数字状态代码的各个值,以及相应的原因短语的示例集,如下所示。此处列出的原因短语仅是建议-可以将其替换为本地等效项,而不会影响协议。”
Ted Bigham

定制原因短语很棒,但是(由于您的消息是“当前密码不匹配”),听起来好像您实际上想要在此处输入代码401,在这种情况下,您可能不需要更改消息。
编码

Answers:


59

您可以查看此res.send(400, 'Current password does not match') Look express 3.x文档以获取详细信息

Expressjs 4.x的更新

使用这种方式(请查看express 4.x docs):

res.status(400).send('Current password does not match');
// or
res.status(400);
res.send('Current password does not match');

41
不幸的是,这不会设置http状态消息,但会发送“当前密码不匹配”作为正文内容...
lgersman 2013年

这确实设置了HTTP状态,但由于不赞成使用此方法签名,因此会发出警告。
空性2014年

1
res.status(400).send('Current password does not match');示例适用于我要快4
泰勒运煤船

Express ^4.16.2
Ajay

103

现有的答案都不能满足OP最初的要求,即要覆盖Express发出的默认原因短语(状态代码后立即显示的文本)。

你想要的是res.statusMessage。这不是Express的一部分,它是Node.js 0.11+中基础http.Response对象的属性。

您可以这样使用它(在Express 4.x中测试):

function(req, res) {
    res.statusMessage = "Current password does not match";
    res.status(400).end();
}

然后使用curl验证其是否有效:

$ curl -i -s http://localhost:3100/
HTTP/1.1 400 Current password does not match
X-Powered-By: Express
Date: Fri, 08 Apr 2016 19:04:35 GMT
Connection: keep-alive
Content-Length: 0

6
这是将设置为statusMessage映射到StatusCode的标准消息以外的其他东西的正确方法
peteb,2013年

4
您可以使用res.nativeResponse.statusMessage
sebilasse

@RobertMoskal使用最小的Express服务器(Express 4.16.1和Node 12.9.0)进行了测试,它仍然对我有用。检查您的应用程序代码:也许其他地方有问题。
mamacdon

不知道为什么这不是公认的答案,因为至少在我写这篇文章时,这肯定是解决方案。
亚伦·萨默斯,

12

在服务器端(Express中间件):

if(err) return res.status(500).end('User already exists.');

在客户端处理

角度:-

$http().....
.error(function(data, status) {
  console.error('Repos error', status, data);//"Repos error" 500 "User already exists."
});

的jQuery:-

$.ajax({
    type: "post",
    url: url,
    success: function (data, text) {
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});

11

快速处理此类自定义错误的一种优雅方法是:

function errorHandler(err, req, res, next) {
  var code = err.code;
  var message = err.message;
  res.writeHead(code, message, {'content-type' : 'text/plain'});
  res.end(message);
}

(您也可以为此使用express'内置的express.errorHandler

然后在您的中间件中,在路由之前:

app.use(errorHandler);

然后在您要创建错误“当前密码不匹配”的位置:

function checkPassword(req, res, next) {
  // check password, fails:
  var err = new Error('Current password does not match');
  err.code = 400;
  // forward control on to the next registered error handler:
  return next(err);
}

err.status = 400; 我相信更普遍。
mkmelin 2015年


3

我的用例正在发送自定义JSON错误消息,因为我正在使用express来驱动我的REST API。我认为这是一个相当普遍的情况,因此在我的回答中将重点介绍该情况。

精简版:

快速错误处理

定义错误处理中间件,就像其他中间件一样,除了使用四个参数而不是三个参数外,特别是使用签名(err,req,res,next)。...在其他app.use()之后,您最后定义错误处理中间件并路由调用

app.use(function(err, req, res, next) {
    if (err instanceof JSONError) {
      res.status(err.status).json({
        status: err.status,
        message: err.message
      });
    } else {
      next(err);
    }
  });

通过执行以下操作从代码的任何位置引发错误:

var JSONError = require('./JSONError');
var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

长版

引发错误的规范方法是:

var err = new Error("Uh oh! Can't find something");
err.status = 404;
next(err)

默认情况下,Express通过将其整洁地打包为带有代码404的HTTP响应和包含消息字符串并附加了堆栈跟踪的主体来处理此问题。

例如,当我使用Express作为REST服务器时,这对我不起作用。我希望将错误以JSON而不是HTML的形式发送回去。我也绝对不希望将堆栈跟踪移到我的客户端。

我可以使用发送JSON作为响应req.json(),例如。像req.json({ status: 404, message: 'Uh oh! Can't find something'})。(可选)我可以使用设置状态代码req.status()。结合两者:

req.status(404).json({ status: 404, message: 'Uh oh! Can't find something'});

这就像一个魅力。就是说,我发现每次遇到错误时都很难键入代码,并且代码不再像next(err)以前那样自我记录。它看起来与发送正常(即有效)响应JSON的方式非常相似。此外,规范方法引发的任何错误仍将导致HTML输出。

这是Express的错误处理中间件出现的地方。作为我的路线的一部分,我定义了:

app.use(function(err, req, res, next) {
    console.log('Someone tried to throw an error response');
  });

我还将Error细分为自定义JSONError类:

JSONError = function (status, message) {
    Error.prototype.constructor.call(this, status + ': ' + message);
    this.status = status;
    this.message = message;
  };
JSONError.prototype = Object.create(Error);
JSONError.prototype.constructor = JSONError;

现在,当我想在代码中引发错误时,我做了:

var err = new JSONError(404, 'Uh oh! Can't find something');
next(err);

回到自定义错误处理中间件,我将其修改为:

app.use(function(err, req, res, next) {
  if (err instanceof JSONError) {
    res.status(err.status).json({
      status: err.status,
      message: err.message
    });
  } else {
    next(err);
  }
}

将Error子类化为JSONError很重要,因为我怀疑Express会instanceof Error检查传递给的第一个参数,next()以确定是否必须调用普通处理程序或错误处理程序。我可以删除该instanceof JSONError检查并进行较小的修改以确保意外错误(例如崩溃)也返回JSON响应。


2

使用Axios时,您可以通过以下方式检索自定义响应消息:

Axios.get(“your_url”)
.then(data => {
... do something
}.catch( err => {
console.log(err.response.data) // you want this
})

...在Express中将其设置为:

res.status(400).send(“your custom message”)

0

如果您的目标只是将其简化为单行/简单行,则可以稍微依赖默认值...

return res.end(res.writeHead(400, 'Current password does not match'));

-2

好吧,在Restify的情况下,我们应该使用sendRaw()方法

语法是: res.sendRaw(200, 'Operation was Successful', <some Header Data> or null)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.