web-dev-qa-db-fra.com

ERR_HTTP_HEADERS_SENT: Impossible de définir les en-têtes après leur envoi au client.

Je suis confronté à ce problème étrange dans NodeJS lorsque j'utilise Passport.js, Express et Mongoose. En gros, j'obtiens une erreur disant "Je ne peux pas définir les en-têtes après leur envoi au client" même si je n'envoie pas plus d'un en-tête.

J'ai lu d'autres articles et les ai essayés, mais aucun d'entre eux n'a fonctionné.

J'ai fouillé dans les problèmes de github et je n'arrive pas à trouver de solution. J'ai le problème que cette erreur est déclenchée lorsque j'envoie des en-têtes à réponses multiples, mais le fait est que je n'envoie pas plusieurs en-têtes. Cela semble juste bizarre.

Voici ma trace de pile:

(node: 9236) DeprecationWarning: l'analyseur de chaîne d'URL actuel est obsolète et sera supprimé dans une version ultérieure. Pour utiliser le nouvel analyseur, passez l'option {useNewUrlParser: true} à MongoClient.connect.

Serveur fonctionnant sur le port 5000
Erreur de connexion MongoDB
[ERR_HTTP_HEADERS_SENT]: impossible de définir les en-têtes après leur envoi au client
À validateHeader (_http_outgoing.js: 503: 11)
À ServerResponse.setHeader (_http_outgoing.js: 510: 3)
Sur ServerResponse.header (/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:767:10)
Sur ServerResponse.json (/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:264:10)
Sur Profile.findOne.then.profile (/Users/lourdesroashan/code/github/devlog/routes/api/profile.js:27:30)
À <anonyme>

Ceci est mon code serveur:

router.get("/userprofile", passport.authenticate('jwt', { session: false }), (req, res) => {

  Profile.findOne({ user: req.user.id }).then(profile => {
    if (!profile) {
      return res.status(404).json({ error: "No Profile Found" });
    }
    else {
      res.json(profile);
    }
  }).catch(err => {
    console.log(err);
  })
});

Je comprends ce que l'erreur signifie, mais d'après ce que je sais, je ne pense pas envoyer plusieurs en-têtes. J'ai même vérifié par console.log qu'un seul des blocs était exécuté.

Merci d'avance! :)

Code complet à: https://github.com/lourdesr/devlog

EDIT:

Je l'ai compris. C'était un problème dans mon passeport.js lors de la tentative d'obtention de l'utilisateur authentifié. J'ai oublié d'utiliser 'return' sur la méthode 'done', qui l'avait provoquée. Je viens d'ajouter la déclaration de retour et cela a fonctionné!

8
lourdesr

Cette erreur particulière se produit lorsque vous essayez d'envoyer plusieurs réponses à la même demande et est généralement provoquée par un code asynchrone incorrect.

Le code que vous indiquez dans votre question ne semble pas être la cause de cette erreur, mais je vois du code empruntant une autre voie ici qui provoquerait cette erreur.

Où vous avez ceci:

if (!user) {
  errors.email = "User not found";
  res.status(404).json({ errors });
}

Vous devez le changer pour:

if (!user) {
  errors.email = "User not found";
  res.status(404).json({ errors });
  // stop further execution in this callback
  return;
}

Vous ne voulez pas que le code continue après que vous ayez terminé res.status(404).json({ errors }); car il essaiera ensuite d'envoyer une autre réponse.


De plus, partout où vous avez ceci:

if (err) throw err;

dans un rappel asynchrone, vous devez le remplacer par quelque chose qui envoie une réponse d'erreur telle que:

if (err) {
    console.log(err);
    res.sendStatus(500);
    return;
}

lancer un rappel asynchrone revient simplement dans le système d’événements node.js et n’est renvoyé nulle part ailleurs. De plus, il n'envoie pas de réponse à la requête http. En d'autres termes, il ne fait pas vraiment ce que le serveur est censé faire. Alors, faites-vous une faveur et n'écrivez jamais ce code sur votre serveur. Lorsque vous obtenez une erreur, envoyez une réponse d'erreur.


Comme il semble que vous soyez nouveau ici, je tiens à vous féliciter d’avoir inclus un lien vers votre code source complet à l’adresse https://github.com/lourdesr/devlog , car c’est uniquement en regardant cela. que j'ai pu voir cet endroit où l'erreur se produit.

17
jfriend00

Désolé pour la réponse tardive, Selon la documentation sur les mangoustes "Les requêtes Mongoose ne sont pas des promesses. Elles ont une fonction .then () pour co et async/wait pour plus de commodité. Cependant, contrairement aux promesses, appeler une requête .then () peut s'exécuter la requête plusieurs fois "

afin d'utiliser des promesses

mongoose.Promise = global.Promise //To use the native js promises

Ensuite

var promise = Profile.findOne({ user: req.user.id }).exec()
promise.then(function (profile){
    if (!profile) {
      throw new Error("User profile not found") //reject promise with error
    }
    return res.status(200).json(profile) //return user profile      
}).catch(function (err){
    console.log(err); //User profile not found
    return res.status(404).json({ err.message }) //return your error msg
})

voici un article de Nice sur le remplacement des rappels avec promesses en mangouste

et cette réponse sur les mangoustes promet la gestion du rejet la mangouste droite promet le traitement du rejet

2
Ivan of uganda

J'ai eu la même erreur en utilisant express et mangouste avec le moteur de template HBS. Je suis allé dans Expressjs et j'ai lu la documentation de res.render. // Si un rappel est spécifié, la chaîne HTML rendue doit être envoyée explicitement. Donc, je n’envoyais pas à l’origine mon code HTML explicitement dans le rappel ,. Ceci est uniquement pour un formulaire de contact btw, pas les informations de connexion, mais GET

//Original
let { username, email } = req.query;  //My get query data easier to read

res.status(200).render('index', { username, email });

//Solution without error. Second param sending data to views, Third param callback

res.status(200).render('index', { username, email }, (err, html)=>{
      res.send(html);
 });
1
Matt Hippensteel

Je recevais cette erreur à cause d'une erreur stupide de ma part. Je dois faire plus attention lorsque je fais référence à mon autre code de travail. La partie vraiment embarrassante est combien de temps j'ai passé à essayer de trouver la cause de l'erreur. Ouf!

Bad:

return res
  .send(C.Status.OK)
  .json({ item });

Bon:

return res
  .status(C.Status.OK)
  .json({ item });
0
TheDarkIn1978