微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

NodeJs:发送到客户端后无法设置标头

如何解决NodeJs:发送到客户端后无法设置标头

我正在使用验证 jwt 令牌在路由中创建一个简单的有效登录检查

在路线中:

router.post("/contacts",async function (req,res,next) {
  await checkLogin(req,next);
  res.send(userController.getContacts());
});

async function checkLogin(req,next) {
  const loggedIn = await userController.isLoggedIn(req);
  if (!loggedIn) {
    res.status(401).json({ error: "You are not authorized" });
  }
}

在控制器中

async function isLoggedIn(req) {
  let token = req.header("authorization");
  if (!token) {
    return false;
  }
  token = token.substring(7); //remove Bearer from the beginning
  return jwt.verify(token,tokenSecret,function (err,decoded) {
    if (typeof decoded == "object" && decoded.email == req.body.email) {
      return true;
    } else {
      return false;
    }
  });
}

使用有效和无效令牌都可以正常工作,但使用无效令牌时我会收到此日志

UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

如果我删除 status(401),则不会显示错误日志。为什么会发生这种情况以及如何在不触发此错误日志的情况下将 HTTP STATUS 设置为 401?

解决方法

您正在调用 checkLogin,它会设置状态代码并回复请求。 checkLogin 完成后,响应已经发送,您不能发送第二个响应。

您缺少的是一些条件逻辑,这些逻辑会在用户未登录的情况下中止处理。通常,这是在中间件中实现的 - 中间件可以在请求到达之前拦截请求处理程序。

我可以看到您的 checkLogin 实现看起来有点像一个中间件函数:它接受一个 next 参数。你可以把它变成这样:

async function checkLogin(req,res,next) {
  const loggedIn = await userController.isLoggedIn(req);
  if (!loggedIn) {
    res.status(401).json({ error: "You are not authorized" });
    return;
  }
  next();
}
router.post("/contacts",checkLogin,function (req,next) {
  res.send(userController.getContacts());
});

这告诉 express.js 首先评估 checkLogin 中间件,只有在中间件调用 next() 时才将控制权传递给处理程序。如果它永远不会调用 next - 控制永远不会被传递,因此经过身份验证的用户的“主要逻辑”将永远不会运行。

在此处阅读有关中间件的更多信息:http://expressjs.com/en/api.html#middleware-callback-function-examples

,

如果用户未在 checkLogin 中登录,您将发送 401,但此方法已在您的 router.post 中调用,因此它将运行路由处理程序中的下一条语句,即 {{1 }}。但是由于您已经发送了 401 状态,节点在这里抱怨它已经回复了客户端,而您正在尝试发送另一个回复。

您的路由处理程序中需要同时拥有 res.send();

res

这应该可以修复错误。

,

如果用户未登录,应用程序尝试发送 2 个响应,这就是错误发生的原因。

第一个回复:

async function checkLogin(req,next) {
  const loggedIn = await userController.isLoggedIn(req);
  if (!loggedIn) {
    res.status(401).json({ error: "You are not authorized" });
  }
}

如果 login 为 false res.status().json() 将向用户发送响应。

第二个回复 现在代码返回到调用上述函数的那一行,因为没有返回语句来停止/跳过执行

router.post("/contacts",async function (req,next) {
  await checkLogin(req,next);
  res.send(userController.getContacts());
});

所以在 await checkLogin(req,next); 之后,res.send(userController.getContacts()); 被调用,这意味着对于一次调用,您的代码尝试发送 2 个响应。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?