未経験からのNestJS入門|ミドルウェア

概要

ミドルウェアとは、ユーザーのリクエストをルートハンドラで処理する前に、呼び出される関数です。これを利用することで、リクエストの処理前に決まった処理を追加することでができます。

これは Express.js に存在するミドルウェアと同様の機能です。

ミドルウェアの機能

ミドルウェアは主に、次のような要件を満たしたいときに使います。

  • 任意のコードの実行
  • 要求オブジェクトと応答オブジェクトを変更
  • 要求と応答のサイクルを終了
  • スタック内の次のミドルウェア関数を呼び出す
  • 現在のミドルウェア関数が要求/応答サイクルを終了しない場合はnext()、次のミドルウェア関数に制御を渡すために呼び出す必要があります。それ以外の場合、リクエストはハングしたままになります。

ミドルウェアの目的

ミドルウェアは、主に以下の目的に利用できます。

  • リクエストの解析
  • レスポンスヘッダーの追加
  • 不正アクセスの禁止

ミドルウェアの使用方法

ミドルウェアを作成するとき、Nest CLI を使う方法が一番簡単です。

以下コマンドを実行し、ミドルウェアを作成してください。

nest g mi middleware/logger

コマンドの実行が完了したら、以下ファイルが作成されます。

// /src/middleware/logger.middleware.ts

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    next();
  }
}

ミドルウェアを作成するためには、NestMiddleware インターフェイスを実装したクラスに@Injextable()デコレーターを付与する必要があります、Nest CLI を使用することで、その作業も必要ありません。

このミドルウェアクラステンプレート内に必要な機能を肉付けしていきましょう。

今回はユーザーからリクエストがあった場合、ログを流す簡単な処理にします。

// /src/middleware/logger.middleware.ts

import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: any, res: any, next: () => void) {
    console.log("Request")
    next();
  }
}

処理が完成したらミドルウェアを Nest アプリケーションに設定しなければいけません。

app.module にミドルウェアを登録しなければいけないのですが、ミドルウェアは@Module デコレータに置かず、configure モジュールクラスのメソッドを使用して設定します。

そのために AppModule クラスに NestModule インターフェースを実装し、configure モジュールクラスのメソッドを利用できるようにしてください。

実装例は以下の通りです。

// /src/app.module.ts

import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersModule } from './users/users.module';
import { LoggerMiddleware } from './middleware/logger.middleware';

@Module({
  imports: [UsersModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('/');
  }
}

forRoutes には、どのパスにアクセスされたときにミドルウェアを実行するかを指定できます。

これで NestJs アプリケーションを実行し、確認してみましょう。

ルートパスアクセス時に、コンソールに Request が表示されたかと思います。

まとめ

今回は簡単なログを出力するだけのミドルウェアを作成してみましたが、作りこむことで、ユーザーごとに処理するデータを変更したり、不正なアクセスを検知したりすることが可能です。

非常に重要な概念なので、サクッと作れるようになっておきましょう。