3秒でわかる
Express でミドルウェアを登録するメソッド。ログや認証など全リクエスト共通の処理を、各ルートに書かず一箇所にまとめて差し込むために使う。
30秒図解
もう少し詳しく
どういうものか
Express でミドルウェアを登録するメソッドです。ミドルウェアとは、リクエストがルートの処理に届く前後に通る関数のことで、req と res と next の 3 つを受け取ります。
第 1 引数にパスを渡すと、そのパスで始まるリクエストにだけ適用されます。省略すると全てのリクエストが通ります。登録した順に上から下へ実行され、next() を呼ばない限りそこで流れが止まります。この「順番が全て」という性質が、app.get などのルート定義との一番の違いです。
なぜ必要か
共通の処理を各ルートへ書き写さずに済むからです。ログの記録、JSON 本文の解析、ログイン確認、CORS の設定などは、どのエンドポイントでも同じことをします。ルートが 50 個あっても登録は一箇所で済みます。
もう一つは、関心事を分けて並べられることです。認証、権限確認、本処理という段階を別々の関数として書き、通す順に並べるだけで組み立てられます。共通処理を止めたいときは 1 行コメントアウトすれば外れます。
具体例
const express = require("express");
const app = express();
// 1. 全リクエストに適用される。next() を呼ばないとここで止まる
app.use((req, res, next) => {
console.log(req.method, req.url);
next();
});
// 2. 組み込みミドルウェア。これが無いと req.body は undefined のまま
app.use(express.json());
// 3. パスを指定すると /admin 以下だけに適用される
app.use("/admin", (req, res, next) => {
if (!req.headers.authorization) {
return res.status(401).json({ error: "unauthorized" });
}
next();
});
app.get("/admin/users", (req, res) => {
res.json([{ id: 1, name: "sato" }]);
});
// 4. 引数 4 つならエラー処理用。ルートより後ろに置く
app.use((err, req, res, next) => {
console.error(err);
res.status(500).json({ error: "internal error" });
});
app.listen(3000);つまずきやすいところ
next() を呼び忘れてリクエストが返ってこない。エラーも出ずブラウザが待ち続けるので、原因が分かりにくい種類の不具合ですexpress.json() をルート定義より後ろに書き、req.body が undefined になる。ミドルウェアは上から順なので、使う側より前に置きますapp.use("/admin") は /admin/users にも当たる前方一致ですnext() を呼んだ後にさらに res.send() を書き、ヘッダー送信済みのエラーになる。返すなら return を付けて抜けます似た用語との違い
| 書き方 | 対象 |
|---|---|
| app.use | メソッドを問わず、指定パス配下の全リクエスト |
| app.get / app.post | 指定したメソッドとパスの完全一致 |
| app.all | 全メソッド。ただしパスは完全一致 |