Middleware

Middleware

미들웨어는 라우트 핸들러보다 전에 호출되는 함수입니다. 미들웨어 기능은 requestresponse에 액세스 할 수 있습니다. 응용 프로그램의 요청-응답주기에서 객체 및 next()미들웨어 함수. next 미들웨어 함수는 일반적으로 next라는 변수로 표시됩니다.

Nest 미들웨어는 기본적으로 express 미들웨어와 동일합니다. 공식 Express 문서의 다음 설명은 미들웨어의 기능을 설명합니다.

미들웨어 기능은 다음 작업을 수행 할 수 있습니다.

  • 어떤 코드를 실행합니다.

  • 요청 및 응답 오브젝트를 변경합니다.

  • 요청-응답주기를 종료합니다.

  • 스택에서 다음 미들웨어 함수를 호출합니다.

  • 현재 미들웨어 함수가 요청-응답주기를 종료하지 않으면 next()를 호출하여 다음 미들웨어 기능으로 제어를 전달하십시오. 그렇지 않으면 요청이 중단됩니다.

함수 또는 @Injectable()데코레이터가 있는 클래스에서 사용자 정의 Nest 미들웨어를 구현합니다. 클래스는 NestMiddleware 인터페이스를 구현해야 하지만, 함수에는 특별한 요구 사항이 없습니다. 클래스 메소드를 사용하여 간단한 미들웨어 기능을 구현하는 것으로 시작하겠습니다.

@@filename(logger.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    console.log('Request...');
    next();
  }
}
@@switch
import { Injectable } from '@nestjs/common';

@Injectable()
export class LoggerMiddleware {
  use(req, res, next) {
    console.log('Request...');
    next();
  }
}

Dependency injection

Nest 미들웨어는 Dependency Injection을 완벽하게 지원합니다. 공급자 및 컨트롤러와 마찬가지로 동일한 모듈 내에서 사용 가능한 종속성을 주입 할 수 있습니다. 평소와 같이 이것은 생성자를 통해 이루어집니다.

Applying middleware

@Module()데코레이터에는 미들웨어를 위한 공간이 없습니다. 대신 모듈 클래스의 configure()메소드를 사용하여 설정합니다. 미들웨어를 포함하는 모듈은 NestModule 인터페이스를 구현해야합니다. AppModule 레벨에서 LoggerMiddleware를 설정해 봅시다.

@@filename(app.module)
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('cats');
  }
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('cats');
  }
}

위의 예에서 우리는 이전에 CatsController 내에 정의 된 /cats 라우트 핸들러에 대해 LoggerMiddleware를 설정했습니다. 또한 미들웨어를 구성 할 때 경로 path 및 요청 method를 포함하는 오브젝트를 forRoutes()메소드에 전달하여 미들웨어를 특정 요청 메소드로 제한할 수도 있습니다. 아래 예제에서, RequestRequest 메소드 열거 형을 가져와 원하는 요청 메소드 유형을 참조하십시오.

@@filename(app.module)
import { Module, NestModule, RequestMethod, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes({ path: 'cats', method: RequestMethod.GET });
  }
}
@@switch
import { Module, RequestMethod } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes({ path: 'cats', method: RequestMethod.GET });
  }
}

Route wildcards

패턴 기반 경로도 지원됩니다. 예를 들어 별표는 와일드 카드로 사용되며 모든 문자 조합과 일치합니다.

forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });

ab*cd 라우트 경로는 abcd, ab_cd, abecd 등과 일치합니다. ?, +, *()문자는 라우트 경로에 사용될 수 있으며 정규 표현식의 하위 집합입니다. 하이픈 (-)과 점 (.)은 문자 그대로 문자열 기반 경로로 해석됩니다.

Middleware consumer

MiddlewareConsumer는 헬퍼 클래스입니다. 미들웨어를 관리하기위한 몇 가지 기본 제공 방법을 제공합니다. 이들 모두는 유창한 스타일에서 간단하게 사슬로 묶을 수 있습니다. forRoutes() 메소드는 단일 문자열, 다중 문자열, RouteInfo 오브젝트, 제어기 클래스 및 다중 제어기 클래스를 사용할 수 있습니다. 대부분의 경우 아마도 컨트롤러 목록을 쉼표로 구분하여 전달할 것입니다. 아래는 단일 컨트롤러를 사용한 예입니다.

@@filename(app.module)
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController);
  }
}
@@switch
import { Module } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule {
  configure(consumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes(CatsController);
  }
}

info 힌트 apply() 메소드는 단일 미들웨어 또는 여러 인수를 사용하여 다중 미들웨어를 지정할 수 있습니다.

미들웨어가 적용되지 않도록 특정 경로를 제외 할 수 있습니다. 기능 미들웨어 대안을 사용하는 대신 지금까지했던 것처럼 클래스를 사용하여 미들웨어를 정의 할 때를 exclude() 메소드 사용하여 특정 경로를 쉽게 제외 할 수 있습니다. 이 방법은 아래와 같이 경로와 메소드를 식별하는 하나 이상의 객체를 제외시킵니다.

consumer
  .apply(LoggerMiddleware)
  .exclude(
    { path: 'cats', method: RequestMethod.GET },
    { path: 'cats', method: RequestMethod.POST }
  )
  .forRoutes(CatsController);

위의 예에서 LoggerMiddlewareexclude()메소드에 전달 된 두 경로를 제외하고 CatsController 내에 정의 된 모든 경로에 바인딩됩니다. exclude()메소드는 기능 미들웨어 (클래스가 아닌 함수에 정의 된 미들웨어; 자세한 내용은 아래 참조)와 작동하지 않습니다. 또한 이 방법은 보다 일반적인 경로 (예: 와일드 카드)에서 경로를 제외하지 않습니다. 해당 레벨의 제어가 필요한 경우 경로 제한 로직을 미들웨어에 직접 배치하고 요청의 URL에 액세스하여 미들웨어 로직을 조건부로 적용해야합니다.

Functional middleware

우리가 사용한 LoggerMiddleware 클래스는 매우 간단합니다. 멤버, 추가 메소드 및 종속성이 없습니다. 클래스 대신 간단한 함수로 정의할 수 없는 이유는 무엇입니까? 사실 우리는 할 수 있습니다. 이 유형의 미들웨어를 기능적 미들웨어라고합니다. 로거 미들웨어를 클래스 기반에서 기능적 미들웨어로 변환하여 차이점을 설명해 보겠습니다.

@@filename(logger.middleware)
export function logger(req, res, next) {
  console.log(`Request...`);
  next();
};

그리고AppModule 내에서 사용하십시오:

@@filename(app.module)
consumer
  .apply(logger)
  .forRoutes(CatsController);

info 힌트 미들웨어에 종속성이 필요하지 않을 때마다 더 간단한 기능적 미들웨어 대안을 사용하는 것이 좋습니다.

Multiple middleware

위에서 언급 한 것처럼 순차적으로 실행되는 여러 미들웨어를 바인딩하려면 apply()메소드 안에 쉼표로 구분 된 목록을 제공하십시오.

consumer.apply(cors(), helmet(), logger).forRoutes(CatsController);

Global middleware

등록된 모든 라우트에 미들웨어를 한 번에 바인딩하려면 INestApplication 인스턴스에서 제공하는use()메소드를 사용할 수 있습니다.

const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);

Last updated