Expressベースのサーバーに認証を追加しようとしています。ルーティングの奇妙な動作に気づいています。
私はこのExpressコードに問題を蒸留しました:
app.get('/', function (req, res) {
console.log('this is reached first');
res.send('Hello');
});
app.get('/', function (req, res) {
console.log('this is not reached');
});
app.get('*', function (req, res) {
console.log('this is reached');
});
'/'を要求すると、最初のハンドラーが呼び出されます。応答を提供し、next()を呼び出しません。したがって、3番目のハンドラー('*')も呼び出されているのを見て驚いています!もう1つの驚きは、3番目のハンドラーに渡される応答('res')が、最初のハンドラーに渡される応答と同じではないことです。(1番目のハンドラーからnext()を呼び出すと、同じ応答オブジェクトで2番目のハンドラーが呼び出されます。)
さて、私の実際のシナリオでは、リクエストを処理し、グローバルな方法で認証を検証したいと思います。ただし、一部のルートは、認証されていないユーザーが引き続き使用できるようにする必要があります。私は自分の解決策をZikesの答えに基づいています。最初に「フリー」パスをルーティングしました。次に、すべてのルートハンドラー('*')を含めました。ユーザーが認証されている場合はnext()を呼び出し、それ以外の場合はnext(err)を呼び出します。以下はすべての「制限された」ルートです。そして最後に、app.useを使用した私自身のエラーハンドラー。これは次のようになります。
app.use(app.router);
app.use(function(err, req, res, next) {
console.log('An error occurred: ' + err);
res.send(401, 'Unauthorized');
});
app.get('/', function (req, res) {
res.send('Hello all');
});
app.all('*', function (req, res, next) {
if (req.user) {
next(); // authorized
} else {
next(new Error('401')); // unauthorized
}
});
app.get('/members', function (req, res) {
res.send('Hello member');
});
これはかなりうまく機能し、「/members」へのアクセスをブロックします。ただし、バグがあります。制限されていないパス('/')にアクセスしている場合でも、認証チェックとエラー処理が発生します。目的の応答が送信された後、エラーハンドラは401エラー応答を送信しようとします。後者は送信されませんが、コードは実行されません。
また、このメカニズムの副作用は、認証されていないユーザーが存在しないページに対して401エラーを受け取ることです。そのような場合には、404を返したいと思うかもしれません。しかし今、私はそれをプッシュしています...
私はちょっと2つの質問があります:
- この動作はバグですか?次に呼び出されることなく、ジェネラルハンドラーを呼び出す必要がありますか?
- 個別にマークを付けることなく、すべてではないが多くのルートをフックするための良い解決策は何でしょうか?