Express.js 中的新 Mongoose Schema `ERR_HTTP_HEADERS_SENT` 错误

Posted

技术标签:

【中文标题】Express.js 中的新 Mongoose Schema `ERR_HTTP_HEADERS_SENT` 错误【英文标题】:New Mongoose Schema `ERR_HTTP_HEADERS_SENT` erorr in Express.js 【发布时间】:2021-09-09 10:52:27 【问题描述】:

我的目标是

如果找到任何数据 findOne() 函数使用内容更新当前端点,如果没有使用 Schema 创建新元素。

问题

如果 db 中没有数据,那么首先if 它会将ERR_HTTP_HEADERS_SENT 与console.log = 1 相结合,但如果有,则使用console.log = 3 一切正常。

  try 
    const find = await endPointSchema.findOne( uuid: uuid );
    if (!find) 
      const data = new endPointSchema(
        uuid: uuid,
        endpoint: [ point: Endpoint, Content ],
        date: Date.now(),
      );
      await data.save();
      console.log(1);
      res.status(200).json( message: "Succesfully Created new Breakpoint" );
      return;
     else 
      if (!find.endpoint) 
        console.log(2);
        res.end();
        return;
       else 
        console.log(3);
        res.end();
        return;
      
    
   catch (e) 
    console.log(e);
    res.end();
    return;
  

我的端点

route.post("/endpoint", AuthorizePanel, async (req, res) => 
  const  role, username, uuid  = req.user;
  if (!role && !username && !uuid) 
    res.sendStatus(401);
    return;
  

  const  Endpoint, Content  = req.body;
  if (Endpoint === username) 
    res.status(403).json( message: "Endpoint can not be same with your username!" );
    return;
  

  try 
    const find = await endPointSchema.findOne( uuid: uuid );
    if (!find) 
      const data = new endPointSchema(
        uuid: uuid,
        endpoint: [ point: Endpoint, Content ],
        date: Date.now(),
      );
      await data.save();
      console.log(1);
      res.status(200).json( message: "Succesfully Created new Breakpoint" );
      return;
     else 
      if (!find.endpoint) 
        console.log(2);
        res.end();
        return;
       else 
        console.log(3);
        res.end();
        return;
      
    
   catch (e) 
    console.log(e);
    res.end();
    return;
  
);

授权面板


import jwt from "jsonwebtoken";

export const AuthorizePanel = (req, res, next) => 
  const authHeader = req.headers.authorization;
  if (authHeader) 
    const token = authHeader.split(" ")[1];
    jwt.verify(token, process.env.JWT_SECRET, (err, user) => 
      if (err) 
        res.sendStatus(403)
        return
      
      req.user = user;
      next();
    );
  
  next();
;

【问题讨论】:

1 在不成功的流程中打印?数据是否保存? 是的,我知道这很有趣,但是在 http 标头错误之后我看到它已保存。 该错误通常是当您在发送一个响应后发送 res 时。查看您的代码,我不明白这是怎么回事。您可以在使用 res 的地方添加/检查更多代码流吗? 就像我无法理解的那样 可能在此函数之前的某个地方还有另一个 res.end() 或 res.send()。 【参考方案1】:

问题在于 auth 中间件,如果您仔细查看 auth 中间件,您会注意到 jwt.verify 函数中的 return 语句仅针对该函数返回。 jwt.verify 函数执行后,next(); 函数也可以工作。要打断你需要在你的第一个 if 块中添加 else 块

export const AuthorizePanel = (req, res, next) => 
  const authHeader = req.headers.authorization;
  if (authHeader) 
    const token = authHeader.split(" ")[1];
    jwt.verify(token, process.env.JWT_SECRET, (err, user) => 
      if (err) 
        res.sendStatus(403)
        return
      
      req.user = user;
      next();
    );
   else 
    next();
  

;

【讨论】:

【参考方案2】:

在 authorizePanel 中,将第二个 next 放在 else 条件中或将其删除(如果您只希望经过身份验证的用户继续前进)。 每次都会调用它。

为什么我认为有错误

为了简化,让我们用 mongoose call function A来调用函数。

您的 JWT 验证代码中有一个回调,因此将在将来某个时间点异步调用它。

如果用户遇到身份验证错误,则请求将尝试返回响应(异步)并调用函数 A(立即因为 if 外部的 next())将发送自己的响应。 此外,如果没有错误,则流程也将转移到功能 A。 (注意因为if条件之外的另一个next(),所以流程已经移到A了)。

在任何一种情况下,您的服务器都可能发送 2 个响应。一个带有 JWT 错误和您的第二个 函数 A。或者两者都来自您的函数 A

可能会保存数据,但之后会出现错误,因为标头已发送,服务器正在尝试再次执行此操作。

【讨论】:

正如我所说,我使用了这个中间件功能,但我从未收到此错误。我认为问题出在端点功能上,所以您会问我如何确定这一点,因为当我替换此功能时,另一个功能不会出现此错误。 你的其他函数是否也发送响应?

以上是关于Express.js 中的新 Mongoose Schema `ERR_HTTP_HEADERS_SENT` 错误的主要内容,如果未能解决你的问题,请参考以下文章

Express.js 项目中在哪里进行验证——在数据库层进行验证(re. Mongoose)?

node.js + express.js:使用 mongodb/mongoose 处理会话

Express.js - Mongoose 多个或条件

在 Mongoose 模型中访问 Express.js 请求上下文

Express Js Mongoose 不抛出 Invalid Column 错误

无法访问 express js router.delete 中的参数