5. Expressミドルウェア
Expressミドルウェアは、Express.JSの根幹的な機構で、Express.JSを使いこなすためには理解しておきたいしくみです。Expressジェネレータが作成するスケルトンではミドルウェアが各所で使われていますし、サードパーティのミドルウェアをNPMで簡単に組み込むこともできます。また、プログラマが独自のミドルウェアを追加してシンプルに機能を拡張することもできます。
5-1. ミドルウェアの概念
ミドルウェアの概念を理解するために、Express.JSの基本的な処理の流れをおさらいします。Express.JSは、ブラウザからHTTPリクエストを受けとり、何らかの処理をしてレスポンスを返します。これをリクエストレスポンスサイクルといいます。
概念的には、ミドルウェアはこの流れの中間に位置する処理のまとまりです。例えて言うなら、コーヒーショップのドライブスルーで入り口から出口までの間に、「注文をとる」「コーヒーを渡す」「代金を受け取る」というミドルウェアがあるようなイメージです。これらの処理は、注文するメニューによらず、どのようなリクエストの場合も共通する処理の流れです。
Express.JSでは、複数のURLパスへのリクエストに対して行う処理をミドルウェアというまとまりにして、リクエストレスポンスサイクルの中間に配置することができます。ミドルウェアはいくつでも登録・実行させることがき、連続したミドルウェアのことをミドルウェアチェーンと呼びます。
5-2. ミドルウェアの実装
実質的には、ミドルウェアは単純にJavaScriptのfunctionです。app.use( )
などの関数を使ってfunctionをマウントします。
実装のイメージを伝えるために仮想のコードを書きます。
1 | /* |
同じことを、以下のように書くこともできます。
1 | /* |
また、.use()
の代わりに.get()
や.put()
というインターフェースが用意されており、リクエストメソッドをGETやPUTに限定してミドルウェアをマウントすることができます。
1 |
|
5-3. ミドルウェアの種類
ミドルウェアには以下のタイプがあります。
- アプリケーション・レベルのミドルウェア
- ルーター・レベルのミドルウェア
- Express本体に標準装備されたミドルウェア
- サード・パーティー・ミドルウェア
5-4. アプリケーション・レベルのミドルウェア
アプリケーション・レベルのミドルウェアはapp = express()
のapp
にマウントするミドルウェアです。マウントするfunctionの引数として次の3つが決められています。
引数1 : リクエストオブジェクト (慣習的にreqという変数名)
引数2 : レスポンスオブジェクト (慣習的にresという変数名
引数3 : 次のミドルウェアに処理を渡すコールバック(慣習的にnextという変数名)
1 | var app = express(); |
この3つの引数が渡されることには次のような意味があります。
req : どのミドルウェアでも、ブラウザからのリクエスト情報を直接知ることができる。
res : どのミドルウェアでも、ブラウザへのレスポンスを直接操作できる。
next : どのミドルウェアも、次のミドルウェアに処理を渡すときはnext()をコールバックする。
resオブジェクトを直接操作できるので、res.send()
などのメソッドを使えば、ミドルウェアの中からリクエストレスポンスサイクルを終了させることができます。以下の例では、エラーのときはres.send()
を実行してリクエストレスポンスサイクルを終了し、正常のときはnext()
で処理を流しています。
1 |
|
もしも、res.send()
もnext()
もどちらも呼ばないコードを書いてしまうと、リクエストに対する処理がそこで行き止まりになってしまい、ブラウザからのリクエストはタイムアウトします。
5-5. ルーター・レベルのミドルウェア
ルーター・レベルのミドルウェアは、router = express.Router()
のrouter
にマウントするミドルウェアです。ルーターが複数あるときに個別のルーターに対してミドルウェアを直接マウントすることができます。
Expressジェネレータで生成されるスケルトンで、既にこのタイプのミドルウェアが使われています。 /routes/users.js を開くと以下のようなコードがありますが、router.get()
の部分はルーター・レベルのミドルウェアです。
1 | /* |
試しにこのスケルトンに対して、「日曜はこのページを利用できないようにする」という機能をミドルウェアとして追加してみます。(このコードは/routers/users.jsなので「このページ」というのは/users/のページということになります。)
1 | /* |
5-6. Express本体に標準装備されたミドルウェア
Express.JS本体にビルトインされているミドルウェアがあります。ここでは個々のミドルウェアの説明を省略します。
- express.static : スタティックなファイルを配信
- express.json : json処理
- express.urlencoded : URLエンコード処理
app.jsのコードを見てみると以下のような記述を見つけることができます。
1 | /* |
このコードをパッと見て気がつきますが、.use( )
のかっこの中がfunction(req,res,next){...}
という形になっていません。
これは、express.json()
やexpress.urlencoded()
が以下のようにfunctionをreturnする構造になっているためで、実質的にはこれまで見てきたミドルウェアの形式と同じことです。
1 | return function (req, res, next) { |
5-7. サード・パーティー・ミドルウェア
npmを使ってインストール可能なミドルウェアがたくさん存在します。Expressジェンレレータが生成するスケルトンでも、以下のようなミドルウェアが使われています。
- cookie-parser : クッキー処理 https://www.npmjs.com/package/cookie-parser
- morgan : ログ処理 https://www.npmjs.com/package/morgan
app.jsのコードを見てみると以下のような記述を見つけることができます。
1 | /* |
この他にも、よく使うサード・パーティー・ミドルウェアには以下のようなものがあります。
- express-session : セッション処理 https://www.npmjs.com/package/express-session
- body-parser : HTTPリクエストのBodyパーサー。フォームでPOST値を取得する際などに使う。
- serve-favicon : favicon配信 https://www.npmjs.com/package/serve-favicon
- passport : ユーザー認証 https://www.npmjs.com/package/passport
まとめ
- Expressミドルウェアは、Expressのリクエストレスポンスサイクルの中間にfunctionを配置するしくみです。
- 以下のような書式で記述できます。
1 | app.use(function(req, res, next){ |
ミドルウェアには以下のようなタイプがあります:
アプリケーション・レベル
ルーター・レベル
Express本体に標準装備
サード・パーティー