Passport.js、Express、およびMongooseで使用するときにNodeJSでこの奇妙な問題に直面しています。基本的に、複数のヘッダーを送信しなくても、「クライアントに送信したヘッダーを設定できません」というエラーが表示されます。
私は他の投稿を読んで試してみましたが、どれも機能しませんでした。
Githubの問題を掘り下げましたが、解決策が見つからないようです。複数の応答ヘッダーを送信するとこのエラーがトリガーされるという問題が発生しますが、実際には複数のヘッダーを送信していません。奇妙に思えます。
これは私のスタックトレースです。
(ノード:9236)DeprecationWarning:現在のURL文字列パーサーは非推奨であり、将来のバージョンで削除されます。新しいパーサーを使用するには、オプション{useNewUrlParser:true}をMongoClient.connectに渡します。
ポート5000で実行されているサーバー
MongoDB接続エラー
[ERR_HTTP_HEADERS_SENT]:ヘッダーがクライアントに送信された後、ヘッダーを設定できません
validateHeader(_http_outgoing.js:503:11)
ServerResponse.setHeader(_http_outgoing.js:510:3)で
ServerResponse.header(/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:767:10)
ServerResponse.json(/Users/lourdesroashan/code/github/devlog/node_modules/express/lib/response.js:264:10)
Profile.findOne.then.profile(/Users/lourdesroashan/code/github/devlog/routes/api/profile.js:27:30)
<匿名>
これは私のサーバーコードです:
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);
})
});
私はエラーの意味を理解していますが、私が知っていることから、複数のヘッダーを送信しているとは思わず、console.logでブロックの1つのみが実行されていることも確認しました。
よろしくお願いします! :)
完全なコード: https://github.com/lourdesr/devlog
編集:
私はそれを考え出した。認証されたユーザーを取得しようとしたときに、passport.jsで問題が発生しました。 「完了」メソッドで「リターン」を使用するのを忘れてしまいました。 returnステートメントを追加するだけで機能しました!
この特定のエラーは、同じリクエストに複数のレスポンスを送信しようとするたびに発生します。通常、不適切な非同期コードが原因です。
質問に表示されるコードは、そのエラーを引き起こすようには見えませんが、別のルートにコードがあります here それはそのエラーを引き起こします。
これがある場所:
_if (!user) {
errors.email = "User not found";
res.status(404).json({ errors });
}
_
次のように変更する必要があります。
_if (!user) {
errors.email = "User not found";
res.status(404).json({ errors });
// stop further execution in this callback
return;
}
_
res.status(404).json({ errors });
を実行した後、別の応答を送信しようとするため、コードを続行したくありません。
さらに、これがあるすべての場所:
_if (err) throw err;
_
非同期コールバック内で、実際にエラーレスポンスを送信するようなものに置き換える必要があります。
_if (err) {
console.log(err);
res.sendStatus(500);
return;
}
_
非同期コールバック内でスローすると、node.jsイベントシステムに戻り、実際にキャッチできる場所にはスローされません。さらに、httpリクエストへの応答を送信しません。言い換えれば、サーバーが行うべきことを実際には行いません。だから、自分自身に感謝し、サーバーにそのコードを書かないでください。エラーが発生したら、エラー応答を送信します。
ここであなたは新しいかもしれないように見えるので、私はあなたの完全なソースコードへのリンクを https://github.com/lourdesr/devlog に含めることであなたをほめたいと思いました。エラーが発生しているこの場所を確認できました。
Lateの応答については申し訳ありません。mongooseのドキュメントによると、「Mongooseクエリは約束ではありません。便宜上、coおよびasync/awaitの.then()関数があります。しかし、約束とは異なり、クエリの.then()クエリ複数回」
約束を使用する
mongoose.Promise = global.Promise //To use the native js promises
それから
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
})
mongooseでの約束を使用したコールバックの切り替え に関する素敵な記事があります
そして、マングースに関するこの回答は、拒否処理を約束します マングースの正しい約束拒否処理
HBSテンプレートエンジンでexpressとmongooseを使用すると、同じエラーが発生しました。 Expressjsに行き、res.renderのドキュメントを読みました。コールバックが指定されている場合は、レンダリングされたHTML文字列を明示的に送信する必要があります。だから私はもともとコールバックで明示的にhtmlを送信していませんでした。これは、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);
});
自分の愚かな間違いのために、このエラーを受け取っていました。他の作業コードを参照するときは、もっと注意する必要があります。本当に恥ずかしいのは、エラーの原因を突き止めるのにどれだけの時間を費やしたかです。うわ!
悪い:
return res
.send(C.Status.OK)
.json({ item });
良い:
return res
.status(C.Status.OK)
.json({ item });