Express アプリケーションで使用するミドルウェアの作成

概要

ミドルウェア 関数は、アプリケーションの要求 - 応答サイクルにおいて、リクエストオブジェクト (req)、レスポンスオブジェクト (res)、および next 関数にアクセスできる関数です。 next 関数は、Express ルータ内の関数であり、呼び出されると、現在のミドルウェアの次のミドルウェアを実行します。

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

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

次の図は、ミドルウェア関数呼び出しの要素を示しています。

ミドルウェア関数が適用される HTTP メソッド。
ミドルウェア関数が適用されるパス (ルート)。
ミドルウェア関数。
ミドルウェア関数へのコールバック引数。慣例により "next" と呼ばれます。
ミドルウェア関数への HTTP レスポンス 引数。慣例により "res" と呼ばれます。
ミドルウェア関数への HTTP リクエスト 引数。慣例により "req" と呼ばれます。

Express 5 以降、Promise を返すミドルウェア関数は、拒否またはエラーをスローするときに next(value) を呼び出します。 next は、拒否された値またはスローされたエラーのいずれかで呼び出されます。

単純な「Hello World」Express アプリケーションの例を次に示します。この記事の残りの部分では、アプリケーションに 3 つのミドルウェア関数を定義して追加します。1 つは単純なログメッセージを出力する myLogger、1 つは HTTP リクエストのタイムスタンプを表示する requestTime、もう 1 つは受信クッキーを検証する validateCookies です。

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

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(3000)

ミドルウェア関数 myLogger

「myLogger」と呼ばれるミドルウェア関数の簡単な例を次に示します。この関数は、アプリへのリクエストが通過するときに「LOGGED」を出力するだけです。ミドルウェア関数は、myLogger という名前の変数に割り当てられます。

const myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

上記の next() の呼び出しに注目してください。この関数を呼び出すと、アプリ内の次のミドルウェア関数が呼び出されます。 next() 関数は Node.js または Express API の一部ではなく、ミドルウェア関数に渡される 3 番目の引数です。 next() 関数は任意の名前にできますが、慣例により常に「next」という名前が付けられます。混乱を避けるため、常にこの規則を使用してください。

ミドルウェア関数をロードするには、ミドルウェア関数を指定して app.use() を呼び出します。たとえば、次のコードは、ルートパス (/) へのルートの前に myLogger ミドルウェア関数をロードします。

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

const myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
}

app.use(myLogger)

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(3000)

アプリがリクエストを受信するたびに、「LOGGED」というメッセージがターミナルに出力されます。

ミドルウェアのロード順序は重要です。最初にロードされたミドルウェア関数が最初に実行されます。

myLogger がルートパスへのルートの後にロードされた場合、リクエストはルートパスに到達することはなく、アプリは「LOGGED」を出力しません。これは、ルートパスのルートハンドラがリクエスト - 応答サイクルを終了するためです。

ミドルウェア関数 myLogger は、メッセージを出力してから、next() 関数を呼び出すことによって、スタック内の次のミドルウェア関数にリクエストを渡します。

ミドルウェア関数 requestTime

次に、「requestTime」と呼ばれるミドルウェア関数を作成し、requestTime と呼ばれるプロパティをリクエストオブジェクトに追加します。

const requestTime = function (req, res, next) {
  req.requestTime = Date.now()
  next()
}

アプリは jetzt die ミドルウェア関数 `requestTime` を使用します。また、ルートパスルートのコールバック関数は、ミドルウェア関数が `req` (リクエストオブジェクト) に追加するプロパティを使用します。

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

const requestTime = function (req, res, next) {
  req.requestTime = Date.now()
  next()
}

app.use(requestTime)

app.get('/', (req, res) => {
  let responseText = 'Hello World!<br>'
  responseText += `<small>Requested at: ${req.requestTime}</small>`
  res.send(responseText)
})

app.listen(3000)

アプリのルートにリクエストを送信すると、アプリはブラウザにリクエストのタイムスタンプを表示するようになります。

ミドルウェア関数 validateCookies

最後に、受信クッキーを検証し、クッキーが無効な場合は 400 レスポンスを送信するミドルウェア関数を作成します。

外部の非同期サービスでクッキーを検証する関数の例を次に示します。

async function cookieValidator (cookies) {
  try {
    await externallyValidateCookie(cookies.testCookie)
  } catch {
    throw new Error('Invalid cookies')
  }
}

ここでは、cookie-parser ミドルウェアを使用して、受信クッキーを req オブジェクトから解析し、cookieValidator 関数に渡します。 validateCookies ミドルウェアは、拒否されるとエラーハンドラを自動的にトリガーする Promise を返します。

const express = require('express')
const cookieParser = require('cookie-parser')
const cookieValidator = require('./cookieValidator')

const app = express()

async function validateCookies (req, res, next) {
  await cookieValidator(req.cookies)
  next()
}

app.use(cookieParser())

app.use(validateCookies)

// error handler
app.use((err, req, res, next) => {
  res.status(400).send(err.message)
})

app.listen(3000)

await cookieValidator(req.cookies) の後に next() がどのように呼び出されるかに注意してください。これにより、cookieValidator が解決された場合、スタック内の次のミドルウェアが呼び出されるようになります。 next() 関数に何か (文字列 'route' または 'router' 以外) を渡すと、Express は現在のリクエストをエラーと見なし、残りのエラー処理以外のルーティングおよびミドルウェア関数をスキップします。

リクエストオブジェクト、レスポンスオブジェクト、スタック内の次のミドルウェア関数、および Node.js API 全体にアクセスできるため、ミドルウェア関数でできることは無限にあります。

Express ミドルウェアの詳細については、Express ミドルウェアの使用 を参照してください。

設定可能なミドルウェア

ミドルウェアを設定可能にする必要がある場合は、オプションオブジェクトまたは他のパラメータを受け入れる関数をエクスポートします。これにより、入力パラメータに基づいてミドルウェア実装が返されます。

ファイル: my-middleware.js

module.exports = function (options) {
  return function (req, res, next) {
    // Implement the middleware function based on the options object
    next()
  }
}

ミドルウェアは jetzt wie unten gezeigt verwendet werden kann.

const mw = require('./my-middleware.js')

app.use(mw({ option1: '1', option2: '2' }))

設定可能なミドルウェアの例については、cookie-session および compression を参照してください。