ミドルウェア
全部のルートに同じことを書きたくない
第4章のつくる回で、5 つのルートが同じ骨格をしていることに気付きました。同じことは、ルートをまたいでも起こります。
届いたリクエストを記録したい。ログインしているか確かめたい。どれも全部のルートで同じ処理が要ります。5 か所にコピーすると、直すときも 5 か所です。
ミドルウェアは、その共通処理を手前にまとめて置く仕組みです。
リクエストが通る道
プレーンテキスト
リクエスト → ミドルウェア → ミドルウェア → ルート → 応答リクエストはルートに届く前に、登録されたミドルウェアを順に通ります。実は express.json() もミドルウェアでした。本文を読める形に直してからルートへ渡す、という共通処理です。
書き方
JavaScript
app.use((req, res, next) => {
console.log(req.method + " " + req.path);
next();
});app.use で登録します。引数が 3 つあるのがミドルウェアの目印です。
req と res はルートと同じですが、next が増えています。
next を呼ばないと止まる
next() は「次へ進んでよい」という合図です。
JavaScript
app.use((req, res, next) => {
console.log("届きました");
// next() を呼ばない
});こう書くと、リクエストはここで止まったまま応答が返りません。ブラウザは待ち続けます。呼び忘れると固まるので、書いたら必ず確かめてください。
逆に、わざと止めるのが正しい場面もあります。第7章の認証では、トークンが無ければ next() を呼ばずに 401 を返して打ち切ります。
登録の順番が実行の順番
ミドルウェアは書いた順に通ります。ですから app.use は、ルートより前に書きます。
JavaScript
app.use(express.json()); // 先に本文を読めるようにして
app.post("/items", ...); // それからルート逆に書くと、ルートに届く時点ではまだ本文が読めません。第4章で express.json() を上のほうに書いていたのは、このためです。
手を動かす
演習では、リクエストを数えるミドルウェアを自作します。next の役割を、自分の手で確かめてください。
要件
app.useでミドルウェアを登録し、logにメソッド パスの形で足す- 足したあと
next()を呼んで次へ進める - ミドルウェアはルートより前に登録する
入出力例
request("GET", "/log") → "200 ["GET /log"]"
request("GET", "/items") → "200 {"count":1}"ヒント
編集 ゆめさく編集部