Express.JS:如何通过名称而不是数字设置响应状态?

24

好的,大家都知道200是OK(即成功),而404表示未找到。但对于诸如永久重定向和临时重定向、需要付款或其他更奇特的HTTP错误代码等内容,最好采取以下做法:

response.status('REQUEST_ENTITY_TOO_LARGE');

不仅使用通常被认为是不好的做法的魔数。当然,我可以在某个对象中使用413:“REQUEST_ENTITY_TOO_LARGE”,但Express已经拥有状态码->名称映射的副本,我宁愿不重复。

如何在Express JS中按名称指定响应状态?

编辑:感谢@Akshat指出http.STATUS_CODES。进一步解释他的答案,由于这些值本身是唯一的,因此可以运行:

   var statusCodeByName = {};
   for ( var number in http.STATUS_CODES ) {
     statusCodeByName[http.STATUS_CODES[number]] = number
   }

这可以让一个人:

  > statusCodeByName['Request Entity Too Large']
  '413'

为什么回答一个数字是不好的?如果你试图不发送它,那么浏览器怎么能区分404和500之间的区别呢?那个数字被浏览器理解得很好。 - Alberto Zaccagni
1
@AlbertoZaccagni 显然,我们需要通过网络发送一个数字,这是RFC2616所要求的。我希望能够通过名称指定状态(显然仍然通过数字发送),这样可以提高可读性。 - mikemaccana
3个回答

32

有一个专门用于此目的的Node模块:http-status-codes。

https://www.npmjs.org/package/http-status-codes

以下是文档内容:

安装

npm install http-status-codes

用法

var HttpStatus = require('http-status-codes');

response.send(HttpStatus.OK);
response.send(
    HttpStatus.INTERNAL_SERVER_ERROR, 
    { error: HttpStatus.getStatusText(HttpStatus.INTERNAL_SERVER_ERROR) }
);

2

HTTP响应代码不是魔术数字;它们是规范。描述性文本只是一种有用的提醒,但协议本身依赖于这些状态码,而核心状态码非常值得学习。有两个想法。您肯定可以在文件顶部创建一个常量并执行此操作:

var REQUEST_ENTITY_TOO_LARGE = 413;
response.status(REQUEST_ENTITY_TOO_LARGE);

然而,大多数REST API只实现以下响应:
200 - OK
201 - Created  # Response to successful POST or PUT
302 - Found # Temporary redirect such as to /login
303 - See Other # Redirect back to page after successful login
304 - Not Modified
400 - Bad Request
401 - Unauthorized  # Not logged in
403 - Forbidden  # Accessing another user's resource
404 - Not Found
500 - Internal Server Error

最后,如果有帮助的话,我将分享我们呈现自定义错误页面的代码:

module.exports = function(app) {

  app.use(function(req, res) {
  // curl https://localhost:4000/notfound -vk
  // curl https://localhost:4000/notfound -vkH "Accept: application/json"
    res.status(404);

    if (req.accepts('html')) {
      res.render('error/404', { title:'404: Page not found', error: '404: Page not found', url: req.url });
      return;
    }

    if (req.accepts('json')) {
      res.send({ title: '404: Page not found', error: '404: Page not found', url: req.url });
    }
  });

  app.use( function(err, req, res, next) {
    // curl https://localhost:4000/error/403 -vk
    // curl https://localhost:4000/error/403 -vkH "Accept: application/json"
    var statusCode = err.status || 500;
    var statusText = '';
    var errorDetail = (process.env.NODE_ENV === 'production') ? 'Sorry about this error' : err.stack;

    switch (statusCode) {
    case 400:
      statusText = 'Bad Request';
      break;
    case 401:
      statusText = 'Unauthorized';
      break;
    case 403:
      statusText = 'Forbidden';
      break;
    case 500:
      statusText = 'Internal Server Error';
      break;
    }

    res.status(statusCode);

    if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
      console.log(errorDetail);
    }

    if (req.accepts('html')) {
      res.render('error/500', { title: statusCode + ': ' + statusText, error: errorDetail, url: req.url });
      return;
    }

    if (req.accepts('json')) {
      res.send({ title: statusCode + ': ' + statusText, error: errorDetail, url: req.url });
    }
  });
};

11
魔数指的是出现在代码中但没有名称的数字(通常不包括0和1)-请参见http://en.wikipedia.org/wiki/Magic_number_(programming)#Unnamed_numerical_constants。 "描述性文本" 实际上是规范的一部分-请参见RFC2616 http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html。此外,与其关注哪些状态码受欢迎,不如关注哪些状态码是*正确的*。 - mikemaccana

1
这是不可能的,除非你愿意自己更改源代码。看一下res.send实现
如果你提供一个字符串作为参数,它会将其解释为html并将响应发送为200。
我认为express使用数字作为HTTP状态码的原因是因为node本身使用数字作为http.STATUS_CODES的对象键。

2
谢谢。http.STATUS_CODES 就是我要找的 - 由于值没有重复,你可以构建一个键值对互换的克隆,并使用它。 - mikemaccana
node --print "JSON.stringify(Object.entries(http.STATUS_CODES).reduce((acc, [key, value]) => (acc[value.replace(/ /g, '_')] = key, acc), {}))" | jq '.' - rofrol

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