#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. Ваша другая функция также отправляет ответ?