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

New Mongoose Schema `ERR_HTTP_HEADERS_SENT` erorr in Express.js

我的目标是

如果找到任何数据,findOne() 函数会使用内容更新当前端点,如果找不到,则使用架构创建新元素。

问题

如果数据库中没有数据,那么首先 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();
};

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

为什么我觉得有误

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

您的 JWT 验证码中有一个回调,因此将在将来的某个时候异步调用

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

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

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

问题出在 auth 中间件中,如果您仔细查看 auth 中间件,您会注意到 jwt.verify 函数中的 return 语句仅为该函数的 returns。 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();
  }

};