Expressミドルウェアの理解

概要: このチュートリアルでは、Expressミドルウェアについて学び、その仕組みを理解します。

Expressミドルウェアの紹介

Expressでは、ミドルウェアは以下のオブジェクトにアクセスできる関数です。

  • リクエストオブジェクト(req)。
  • レスポンスオブジェクト(res)。
  • 次のミドルウェア関数(next)。

技術的には、Expressアプリケーションは一連のミドルウェア関数呼び出しです。

express middleware

以下はミドルウェア関数を定義します。

function fn(req, res, next) {
   // ...
}Code language: JavaScript (javascript)

通常、ミドルウェアは以下のタスクを実行するために使用します。

  • リクエストオブジェクトとレスポンスオブジェクトを変更する。
  • リクエスト/レスポンスサイクルを終了する。
  • リクエスト/レスポンスサイクルに、検証、認証、承認などのカスタムロジックを追加する。
  • そして、次のミドルウェア関数を呼び出す。

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

function fn(req, res, next) {
   // ... 
   next();
}Code language: JavaScript (javascript)

next()関数を呼び出さないと、リクエストはハングしたままになります。

関数内でリクエスト/レスポンスサイクルを終了するには、次のいずれかのメソッドを使用してクライアントに応答を送信する必要があります。

メソッド意味
res.send()レスポンスボディを送信し、リクエスト/レスポンスサイクルを終了します。
res.json()JSONレスポンスを送信し、リクエスト/レスポンスサイクルを終了します。
res.redirect()クライアントを別のURLにリダイレクトし、リクエスト/レスポンスサイクルを終了します。
res.end()データを送信せずにリクエスト/レスポンスサイクルを終了します。

Expressミドルウェアのタイプ

Expressアプリには、次のタイプのミドルウェアがあります。

  • アプリケーションレベルミドルウェア
  • ルーターレベルミドルウェア
  • 組み込みミドルウェア
  • サードパーティミドルウェア
  • エラー処理ミドルウェア

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

アプリケーションレベルのミドルウェアをExpressアプリオブジェクトのインスタンスにバインドする方法は2つあります。

まず、ミドルウェア関数をapp.use()関数に渡します。

import express from 'express';
const app = express();

// define a middleware
const middleware = (req, res, next) {
    console.log("Execute the middleware");
    next();
}

app.use(middleware);

// ...Code language: JavaScript (javascript)

次に、ミドルウェア関数をapp.get()app.post()などのapp.METHOD()関数に渡します。

import express from 'express';
const app = express();

// define a middleware
const middleware = (req, res, next) {
    console.log("Execute the middleware");
    next();
}

app.get('/', middleware, (req, res) => {
    // route handler
});

// ...Code language: JavaScript (javascript)

ルートハンドラーもミドルウェア関数であることに注意してください。

(req, res) => {
    // ...
}Code language: JavaScript (javascript)

ただし、ルートハンドラーは、多くの場合、res.send()またはres.json()メソッドの呼び出しでリクエスト/レスポンスサイクルを終了します。したがって、next関数を渡して、ルーターハンドラー内で呼び出す必要はありません。

次の例では、リクエストメソッドとURLをコンソールウィンドウに記録するアプリケーションミドルウェアを定義します。

import express from 'express';

const PORT = process.env.PORT || 3000;
const app = express();

// define a middleware
const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};

// register the middleware
app.use(log);

// router handlers
app.get('/', (req, res) => {
  res.send('Home');
});

app.get('/about', (req, res) => {
  res.send('About');
});

app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

どのように機能するか。

まず、リクエストのURLとメソッドをコンソールに表示するlogというミドルウェア関数を定義します。

const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};Code language: JavaScript (javascript)

次に、app.use()メソッドを使用してミドルウェアを登録します。

app.use(log);Code language: JavaScript (javascript)

logミドルウェア関数は、/ および /aboutを含むすべてのルートのすべてのリクエストに対して実行されます。

パス /GETリクエストを行うと、Expressはlogミドルウェア関数を実行し、コンソールにログメッセージを表示します。

Request: GET /Code language: JavaScript (javascript)

同様に、/aboutパスにGETリクエストを行うと、logミドルウェア関数が実行され、次の内容がコンソールに表示されます。

Request: GET /aboutCode language: JavaScript (javascript)

ミドルウェアは、ルーターハンドラーの前に登録する必要があることに注意してください。そうしないと、ミドルウェアは有効になりません。例:

import express from 'express';

const PORT = process.env.PORT || 3000;
const app = express();

// define a middleware
const log = (req, res, next) => {
  console.log(`Request: ${req.method} ${req.url}`);
  next();
};

// router handlers
app.get('/', (req, res) => {
  res.send('Home');
});

app.get('/about', (req, res) => {
  res.send('About');
});


// register a middleware
app.use(log); // DO NOT RUN for the / and /about routes


app.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});Code language: JavaScript (javascript)

この例では、ミドルウェアの登録はすべてのルーターハンドラーの後に行われます。/および/aboutルートをリクエストすると、ミドルウェアは効果を発揮しません。

/aboutメソッドでのみlogミドルウェア関数を実行するには、次のように対応するルートハンドラーに渡すことができます。

// ...

app.get('/about', log, (req, res) => {
  res.send('About');
});

// ...Code language: JavaScript (javascript)

この場合、logミドルウェア関数は、/aboutルートのGETメソッドでのみ実行されます。

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

ルーターレベルのミドルウェアは、Expressアプリのインスタンスではなく、Routerインスタンスにバインドされている点を除いて、アプリケーションレベルのミドルウェアと同じです。

ルーターレベルのミドルウェアについては、Expressルーターチュートリアルで説明します。

組み込みミドルウェア

Expressには、いくつかの組み込みミドルウェア関数が用意されています。

  • express.jsonミドルウェアを使用すると、JSONボディでリクエストを解析できます。(Express 4.16.0以降で利用可能)。
  • express.staticミドルウェアは、HTMLファイルや画像などの静的アセットを提供します。
  • express.urlencodedは、URLエンコードされたボディでリクエストを解析します。

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

多くのサードパーティミドルウェアが利用可能です。サードパーティミドルウェアを使用すると、Expressアプリの機能を拡張できます。

サードパーティミドルウェアは、npmなどのパッケージマネージャーを介したインストールが必要です。今後のチュートリアルで、最も一般的に使用されるサードパーティミドルウェアのいくつかを紹介します。

エラー処理ミドルウェア

通常​​のミドルウェアとは異なり、エラー処理ミドルウェアは3つではなく4つのパラメーターを取ります。

function fn(err, req, res, next) {
   // ...
}Code language: JavaScript (javascript)

エラー処理ミドルウェアの最初の引数はエラーオブジェクトです。エラー処理ミドルウェアについては、エラー処理チュートリアルで説明します。

概要

  • ミドルウェアは、リクエスト、レスポンス、および次のミドルウェア関数にアクセスできる関数です。
  • ミドルウェアを登録するには、app.use()関数を使用します。
  • 特定のルートハンドラーにミドルウェアを適用するには、これらのルートハンドラーの前にミドルウェアを登録します。
このチュートリアルは役に立ちましたか?