Новая схема мангуста `ERR_HTTP_HEADERS_SENT` ошибка в Express.js

#javascript #node.js #express #mongoose #nosql

Вопрос:

Моя Цель —

Если вы нашли какие-либо данные, функция 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 amp;amp; !username amp;amp; !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. 1 печатается в неудачном потоке? И сохраняются ли данные?

2. да, это интересно, я знаю, но после ошибки заголовка http я вижу, что он сохранен.

3. Ошибка обычно возникает, когда вы отправляете резюме после того, как один ответ уже отправлен. Глядя на ваш код, я не понимаю, как это происходит. Вы можете добавить/проверить больше своего потока кода там, где вы используете res?

4. Как то, чего я не мог понять

5. Возможно, еще один res.end() или res.send() где-то в этой функции перед этим.

Ответ №1:

Проблема заключается в промежуточном ПО аутентификации, если вы внимательно посмотрите на промежуточное ПО аутентификации, вы заметите оператор return в функции jwt.verify, которая возвращает только для этой функции. После выполнения функции jwt.verify функция next(); также работает. Чтобы прервать это, вам нужно добавить блок else в свой первый блок if

 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 или удалите его (если вы хотите, чтобы продвигались только аутентифицированные пользователи). Его вызывают каждый раз.

Почему я думаю, что есть ошибка

Для упрощения вызовем функцию с помощью функции вызова мангуста A.

В вашем коде проверки JWT есть обратный вызов, поэтому в какой-то момент в будущем он будет вызван асинхронно.

Если у пользователя произошла ошибка аутентификации, запрос попытается вернуть ответ(асинхронно), а также вызовет функцию A (немедленно из-за следующего() вне if), которая отправит свой собственный ответ. Кроме того, если ошибки нет, то поток тоже перейдет к функции А. (Обратите внимание, что из-за другого next() вне условия if поток уже переместился в A).

В любом из этих случаев ваш сервер может отправить 2 ответа. Один с ошибкой JWT и с вашей второй функцией A. Или и то, и другое из вашей функции A.

Данные могут быть сохранены, но после этого возникнет ошибка, поскольку заголовки уже отправлены, и сервер пытается сделать это снова.

Комментарии:

1. Как я уже говорил, я использовал эту функцию промежуточного ПО, но я никогда не получал этой ошибки. Я думаю, что проблема в конечной функции, поэтому вы спросите меня, как вы можете быть уверены в этом, потому что, когда я заменяю эту функцию, другая функция не получает этой ошибки.

2. Ваша другая функция также отправляет ответ?