Black Lives Matter(黒人の命は大切だ)。
Equal Justice Initiativeを支援しましょう.

ミドルウェアの使用

Expressは、独自の最小限の機能を持つルーティングおよびミドルウェアWebフレームワークです。Expressアプリケーションは、本質的に一連のミドルウェア関数呼び出しです。

ミドルウェア関数とは、リクエストオブジェクト(req)、レスポンスオブジェクト(res)、およびアプリケーションのリクエスト/レスポンスサイクルにおける次のミドルウェア関数にアクセスできる関数のことです。次のミドルウェア関数は、通常、nextという名前の変数で示されます。

ミドルウェア関数は、次のタスクを実行できます

現在のミドルウェア関数がリクエスト/レスポンスサイクルを終了しない場合は、next()を呼び出して、次のミドルウェア関数に制御を渡す必要があります。そうしないと、リクエストはハングしたままになります。

Expressアプリケーションは、次の種類のミドルウェアを使用できます

オプションのマウントパスを使用して、アプリケーションレベルおよびルーターレベルのミドルウェアをロードできます。また、一連のミドルウェア関数をまとめてロードすることもできます。これにより、マウントポイントにミドルウェアシステムのサブスタックが作成されます。

アプリケーションレベルのミドルウェア

app.use()関数およびapp.METHOD()関数を使用して、appオブジェクトのインスタンスにアプリケーションレベルのミドルウェアをバインドします。ここで、METHODは、ミドルウェア関数が処理するリクエストのHTTPメソッド(GET、PUT、またはPOSTなど)を小文字で表したものです。

この例は、マウントパスのないミドルウェア関数を示しています。この関数は、アプリがリクエストを受信するたびに実行されます。

const express = require('express')
const app = express()

app.use((req, res, next) => {
  console.log('Time:', Date.now())
  next()
})

この例は、/user/:idパスにマウントされたミドルウェア関数を示しています。この関数は、/user/:idパスに対する任意の種類のHTTPリクエストに対して実行されます。

app.use('/user/:id', (req, res, next) => {
  console.log('Request Type:', req.method)
  next()
})

この例は、ルートとそのハンドラー関数(ミドルウェアシステム)を示しています。この関数は、/user/:idパスへのGETリクエストを処理します。

app.get('/user/:id', (req, res, next) => {
  res.send('USER')
})

これは、マウントパスを使用して、マウントポイントに一連のミドルウェア関数をロードする例です。これは、/user/:idパスへの任意の種類のHTTPリクエストのリクエスト情報を出力するミドルウェアサブスタックを示しています。

app.use('/user/:id', (req, res, next) => {
  console.log('Request URL:', req.originalUrl)
  next()
}, (req, res, next) => {
  console.log('Request Type:', req.method)
  next()
})

ルートハンドラーを使用すると、パスに対して複数のルートを定義できます。以下の例では、/user/:idパスへのGETリクエストに対して2つのルートを定義しています。2番目のルートは問題を引き起こしませんが、最初のルートがリクエスト/レスポンスサイクルを終了するため、呼び出されることはありません。

この例は、/user/:idパスへのGETリクエストを処理するミドルウェアサブスタックを示しています。

app.get('/user/:id', (req, res, next) => {
  console.log('ID:', req.params.id)
  next()
}, (req, res, next) => {
  res.send('User Info')
})

// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
  res.send(req.params.id)
})

ルーターミドルウェアスタックの残りのミドルウェア関数をスキップするには、next('route')を呼び出して、次のルートに制御を渡します。注意: next('route')は、app.METHOD()またはrouter.METHOD()関数を使用してロードされたミドルウェア関数でのみ機能します。

この例は、/user/:idパスへのGETリクエストを処理するミドルウェアサブスタックを示しています。

app.get('/user/:id', (req, res, next) => {
  // if the user ID is 0, skip to the next route
  if (req.params.id === '0') next('route')
  // otherwise pass the control to the next middleware function in this stack
  else next()
}, (req, res, next) => {
  // send a regular response
  res.send('regular')
})

// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
  res.send('special')
})

ミドルウェアは、再利用のために配列で宣言することもできます。

この例は、/user/:idパスへのGETリクエストを処理するミドルウェアサブスタックを含む配列を示しています

function logOriginalUrl (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}

function logMethod (req, res, next) {
  console.log('Request Type:', req.method)
  next()
}

const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
  res.send('User Info')
})

ルーターレベルのミドルウェア

ルーターレベルのミドルウェアは、express.Router()のインスタンスにバインドされていることを除いて、アプリケーションレベルのミドルウェアと同じように機能します。

const router = express.Router()

router.use()関数およびrouter.METHOD()関数を使用して、ルーターレベルのミドルウェアをロードします。

次のコード例は、ルーターレベルのミドルウェアを使用して、上記のアプリケーションレベルのミドルウェアに示されているミドルウェアシステムを複製しています

const express = require('express')
const app = express()
const router = express.Router()

// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
  console.log('Time:', Date.now())
  next()
})

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', (req, res, next) => {
  console.log('Request URL:', req.originalUrl)
  next()
}, (req, res, next) => {
  console.log('Request Type:', req.method)
  next()
})

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', (req, res, next) => {
  // if the user ID is 0, skip to the next router
  if (req.params.id === '0') next('route')
  // otherwise pass control to the next middleware function in this stack
  else next()
}, (req, res, next) => {
  // render a regular page
  res.render('regular')
})

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res, next) => {
  console.log(req.params.id)
  res.render('special')
})

// mount the router on the app
app.use('/', router)

ルーターの残りのミドルウェア関数をスキップするには、next('router')を呼び出して、ルーターインスタンスから制御を戻します。

この例は、/user/:idパスへのGETリクエストを処理するミドルウェアサブスタックを示しています。

const express = require('express')
const app = express()
const router = express.Router()

// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
  if (!req.headers['x-auth']) return next('router')
  next()
})

router.get('/user/:id', (req, res) => {
  res.send('hello, user!')
})

// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
  res.sendStatus(401)
})

エラー処理ミドルウェア

エラー処理ミドルウェアは、常に4つの引数を取ります。エラー処理ミドルウェア関数として識別するには、4つの引数を指定する必要があります。nextオブジェクトを使用する必要がない場合でも、署名を維持するために指定する必要があります。そうしないと、nextオブジェクトは通常のミドルウェアとして解釈され、エラーの処理に失敗します。

他のミドルウェア関数と同様にエラー処理ミドルウェア関数を定義しますが、3つの引数ではなく4つの引数で、特に(err, req, res, next)という署名で定義します

app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

エラー処理ミドルウェアの詳細については、「エラー処理」を参照してください。

組み込みミドルウェア

バージョン4.x以降、ExpressはConnectに依存しなくなりました。以前にExpressに含まれていたミドルウェア関数は、別のモジュールに含まれています。「ミドルウェア関数リスト」を参照してください。

Expressには、次の組み込みミドルウェア関数があります

サードパーティミドルウェア

サードパーティミドルウェアを使用して、Expressアプリに機能を追加します。

必要な機能のNode.jsモジュールをインストールしてから、アプリケーションレベルまたはルーターレベルでアプリにロードします。

次の例は、cookie解析ミドルウェア関数cookie-parserのインストールとロードを示しています。

$ npm install cookie-parser
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')

// load the cookie-parsing middleware
app.use(cookieParser())

Expressで一般的に使用されるサードパーティミドルウェア関数の部分的なリストについては、「サードパーティミドルウェア」を参照してください。