logo

Nest.jsでレスポンスのマッピングをする

2022-12-11
2 years ago

開発環境

  • NestJS
  • Prisma

前提

ORMはPrismaを利用しています。

本題

はじめに

サインアップ、ログインなどユーザー周りの認証を作っている中で、認証をパスしたユーザーのオブジェクトをクライアント側にレスポンスするケースはあると思います。

そんな時、パスワードなどはレスポンスに含めたくないと思います。

今回はそんなレスポンスデータの変更を行うサンプルとして、公式を参考に作ります。

選択肢

  • 特定のフィールド(今回だとpassword)をコントローラごとに取り除く → DRYでない、エラーの余地が多そうなので X
  • class-transformerを利用する方法 → 今回Prismaを利用してますが、こちらの方法もあるようです。ただ今回は X
  • カスタムインターセプターを作る → 公式ドキュメントもあったのでこちらでやってみます

実装

  1. interceptorのファイルを作成し、passwordを取り除く
import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response<T> {
  data: T;
}

@Injectable()
export class RemovePasswordInterceptor<T>
  implements NestInterceptor<T, Response<T>>
{
  intercept(
    context: ExecutionContext,
    next: CallHandler
  ): Observable<Response<T>> {
    return next.handle().pipe(
      map((value) => {
        if (value?.password) {
          value.password = undefined;
        }
        return value;
      })
    );
  }
}
auth.interceptor.ts
  1. グローバルに設定する
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { RemovePasswordInterceptor } from './auth/interceptor/auth.interceptor';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

	# 追加
  app.useGlobalInterceptors(new RemovePasswordInterceptor());

  await app.listen(3000);
}
bootstrap();
main.ts

さいごに

1 ~ 2 で簡単に特定のフィールド(今回はpassword)をレスポンスから除外できました。

サンプルではグローバルに設定していますが、コントローラレベル、メソッドレベルで設定できるので色々と活用できそうです。

参照