Express.jsのミドルウェアを作成し使用する方法

Express.jsのミドルウェアの作成と使用方法を紹介します。コードもGit Hubに掲載するので参考にしてください。

概要

Expressは、ミドルウェア(middleware)を使用して、リクエストとレスポンスの間で処理を実行する能力を持つフレームワークです。ミドルウェアは、リクエストオブジェクト、レスポンスオブジェクト、および次のミドルウェア関数へのアクセスを提供します。ミドルウェアは、Expressのルートハンドラ内で使用されます。

ここでは、以下のバージョンを使用して、Expressでミドルウェアを作成する方法を紹介します。

  • Express v4.17.1
  • nodejs v19.7.0

また、今回作成するコードは全て、GitHubに掲載しています。

ミドルウェアの定義方法

Express.jsでは、ミドルウェアを使用するための主な5つの方法があります。

  1. アプリケーションレベルミドルウェア
    全体のアプリケーションに適用されるミドルウェアです。app.use()またはapp.METHOD()を用いて定義します。
const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('This is an application-level middleware');
  next();
});
  1. ルーターレベルミドルウェア
    特定のルート、もしくはルートグループに対して適用されるミドルウェアです。router.use()またはrouter.METHOD()を用いて定義します。
const express = require('express');
const router = express.Router();

router.use((req, res, next) => {
  console.log('This is a router-level middleware');
  next();
});

app.use('/api', router);
  1. 組み込みミドルウェア
    Expressに組み込まれているミドルウェア関数です。例えばexpress.staticexpress.jsonexpress.urlencodedなどがあります。
app.use(express.json()); // for parsing application/json
app.use(express.static('public')); // to serve static files
  1. サードパーティミドルウェア
    サードパーティによって提供されるミドルウェアです。app.use()またはrouter.use()で適用します。例えば、Cookieをパースするためのcookie-parserやHTTPリクエストログを作成するためのmorganなどがあります。
const cookieParser = require('cookie-parser');
app.use(cookieParser());
  1. エラーハンドリングミドルウェア
    他のミドルウェア関数

で発生したエラーを処理するためのミドルウェアです。通常は4つの引数(err, req, res, next)を持ちます。

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

これらのミドルウェアは、個々の要求がアプリケーションを通過する際に特定のポイントで機能を実行するのに役立ちます。それぞれのミドルウェア関数は、要求-応答サイクルを終了させるか、スタック内の次のミドルウェア関数に要求と応答オブジェクトを渡すかします。

アプリケーションレベルミドルウェアを作成する方法

以下の例では、myMiddlewareという名前のアプリケーションレベルのミドルウェアを作成します。

application.js

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

function myMiddleware(req, res, next) {
  // ミドルウェアの処理
  console.log('ミドルウェアの実行');
  next();
}

app.use(myMiddleware);

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

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解説

  • Expressのインスタンスを作成
const express = require('express');
const app = express();

Expressモジュールをインポートし、そのインスタンスを作成します。

  • ミドルウェア関数の定義
function myMiddleware(req, res, next) {
  // ミドルウェアの処理
  console.log('ミドルウェアの実行');
  next();
}

myMiddlewareという名前のミドルウェア関数を定義します。この関数は、リクエストとレスポンスオブジェクトを引数に取り、次のミドルウェアまたはルートハンドラーに処理を渡すためのnext関数を呼び出します。

  • ミドルウェアの追加
app.use(myMiddleware);

Expressアプリケーションにミドルウェアを追加します。app.useメソッドを使用して、myMiddleware関数をミドルウェアとして登録します。このミドルウェアは、全てのルートハンドラーが実行される前に呼び出されます。

  • ルートハンドラの定義
app.get('/', (req, res) => {
  res.send({ message: 'Hello, World!' });
});

/というパスへのGETリクエストをハンドリングするルートハンドラーを定義します。リクエストが来ると、{ message: 'Hello, World!' }というオブジェクトをレスポンスとして返します。

  • サーバーの起動
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Expressのインスタンスをポート3000でリッスンさせ、サーバーを起動します。サーバーが起動したら、“Server is running on port 3000"というメッセージをコンソールに出力します。

テスト

curl -X GET http://localhost:3000

ルーターレベルミドルウェアを作成する方法

以下の例では、myMiddlewareという名前のルーターレベルのミドルウェアを作成します。

routeMiddleware.js

function myMiddleware(req, res, next) {
  // ミドルウェアの処理
  console.log('ミドルウェアの実行');
  next();
}

module.exports = myMiddleware;

解説

  • ミドルウェア関数の定義
function myMiddleware(req, res, next) {
  // ミドルウェアの処理
  console.log('ミドルウェアの実行');
  next();
}

myMiddlewareという名前のミドルウェア関数を定義します。この関数は、リクエストとレスポンスオブジェクトを引数に取り、次のミドルウェアまたはルートハンドラーに処理を渡すためのnext関数を呼び出します。

  • ミドルウェア関数のエクスポート
module.exports = myMiddleware;

myMiddleware関数をエクスポートします。これにより、他のファイルからこのミドルウェア関数をインポートして使用することができます。

routeMain.js

const express = require('express');
const app = express();
const myMiddleware = require('./myMiddleware');

app.use(myMiddleware);

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

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解説

  • Expressのインスタンスの作成
const express = require('express');
const app = express();

Expressモジュールをインポートし、そのインスタンスを作成します。

  • ミドルウェアのインポート
const myMiddleware = require('./myMiddleware');

myMiddlewareという名前のミドルウェア関数を別のファイルからインポートします。

  • ミドルウェアの登録
app.use(myMiddleware);

app.use()メソッドを使用して、インポートしたミドルウェア関数をExpressアプリケーションに登録します。これにより、このミドルウェア関数はアプリケーションの全てのルートに対して実行されます。

  • ルートハンドラの定義
app.get('/', (req, res) => {
  res.send({ message: 'Hello, World!' });
});

/というパスへのGETリクエストをハンドリングするルートハンドラーを定義します。リクエストが来ると、{ message: 'Hello, World!' }というJSONレスポンスを返します。

  • サーバーの起動
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Expressのインスタンスをポート3000でリッスンさせ、サーバーを起動します。サーバーが起動したら、“Server is running on port 3000"というメッセージをコンソールに出力します。

テスト

curl -X GET http://localhost:3000

組み込みミドルウェアを利用する方法

Expressフレームワークには組み込みのミドルウェアがあり、これらは特定の機能を提供します。例えば、以下のようなコードで静的ファイルを提供することができます。

builtin.js

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

// express.staticミドルウェアを使用して静的ファイルを提供する
app.use(express.static('public'));

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解説

  • Expressのインスタンスの作成
const express = require('express');
const app = express();

Expressモジュールをインポートし、そのインスタンスを作成します。

  • 静的ファイルの提供
app.use(express.static('public'));

express.staticミドルウェアを使用して、publicディレクトリ内の静的ファイルを提供します。これにより、publicディレクトリ内のファイルは、そのファイル名をパスとして直接アクセスできます。例えば、publicディレクトリ内にsample.txtというファイルがある場合、http://localhost:3000/sample.txtというURLでその画像にアクセスできます。

  • サーバーの起動
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Expressのインスタンスをポート3000でリッスンさせ、サーバーを起動します。サーバーが起動したら、“Server is running on port 3000"というメッセージをコンソールに出力します。

テスト

curl -X GET http://localhost:3000/sample.txt

このコードは、publicディレクトリ内の静的ファイルを提供します。例えば、ブラウザでhttp://localhost:3000/sample.txtにアクセスすると、public/sample.txtが表示されます。

サードパーティミドルウェアを利用する方法

Expressでは、NPMから利用可能なサードパーティのミドルウェアを利用することができます。例えば、以下のようなコードでmorganというログ出力用のミドルウェアを利用することができます。

まず、morganパッケージをプロジェクトにインストールします。

npm install morgan

次に、このパッケージをアプリケーションに組み込むためのコードを記述します。

thirdparty.js

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

// morganミドルウェアを使用してログを出力する
app.use(morgan('dev'));

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

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解説

  • ExpressとMorganのインスタンスの作成
const express = require('express');
const morgan = require('morgan');
const app = express();

ExpressとMorganモジュールをインポートします。そして、Expressのインスタンスを作成します。

  • ログ出力の設定
app.use(morgan('dev'));

Morganミドルウェアを使用して、ログを出力します。ここでは、‘dev’フォーマットを使用しています。これにより、リクエストごとに短いレスポンスメッセージがコンソールに出力されます。

  • ルートハンドラの定義
app.get('/', (req, res) => {
  res.send({ message: 'Hello, World!' });
});

ルート(’/’)へのGETリクエストをハンドリングします。リクエストが来ると、‘Hello, World!‘というメッセージを含むJSONオブジェクトをレスポンスとして返します。

  • サーバーの起動
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Expressのインスタンスをポート3000でリッスンさせ、サーバーを起動します。サーバーが起動したら、“Server is running on port 3000"というメッセージをコンソールに出力します。

テスト

curl -X GET http://localhost:3000

このコードは、すべてのリクエストに対してmorganミドルウェアが実行され、それによってHTTPリクエストの詳細がコンソールに出力されます。

エラーハンドリングミドルウェアの作成方法

エラーハンドリングミドルウェアは、他のミドルウェアから渡されたエラーを処理します。エラーハンドリングミドルウェアは、他のミドルウェアとは異なり、4つの引数(err, req, res, next)を取ります。以下はエラーハンドリングミドルウェアの作成例です。

errorhandling.js

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

app.get('/', (req, res) => {
  throw new Error('Something went wrong');
});

// エラーハンドリングミドルウェア
app.use((err, req, res, next) => {
  console.error(err.message);
  res.status(500).send('Something went wrong');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

解説

  • Expressのインスタンスの作成
const express = require('express');
const app = express();

Expressモジュールをインポートし、そのインスタンスを作成します。

  • ルートハンドラの定義
app.get('/', (req, res) => {
  throw new Error('Something went wrong');
});

ルート(’/’)へのGETリクエストをハンドリングします。リクエストが来ると、エラーをスローします。

  • エラーハンドリングミドルウェアの定義
app.use((err, req, res, next) => {
  console.error(err.message);
  res.status(500).send('Something went wrong');
});

エラーハンドリングミドルウェアを定義します。このミドルウェアは、エラーがスローされた場合に実行されます。エラーメッセージをコンソールに出力し、ステータスコード500とともにエラーメッセージをレスポンスとして送信します。

  • サーバーの起動
app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

Expressのインスタンスをポート3000でリッスンさせ、サーバーを起動します。サーバーが起動したら、“Server is running on port 3000"というメッセージをコンソールに出力します。

テスト

curl -X GET http://localhost:3000/

このコードでは、’/‘のルートにGETリクエストが来た時にエラーをスローします。このエラーはエラーハンドリングミドルウェアによってキャッチされ、エラーメッセージがコンソールに出力されます。また、クライアントに対しては500エラー(Internal Server Error)とともにエラーメッセージが返されます。