본문으로 바로가기

Nest Middleware

category Node, Nest, Deno/🦁 Nest.js 2020. 11. 24. 05:09

docs.nestjs.com/middleware

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

Nest middleware are, by default, equivalent to express middleware. 즉, express의 미들웨어와 동등하다. 따라서 개념적인 설명은 생략하고 바로 작성해보도록하자.

 

Middleware

NestMiddleware interface를 implements한 다음 미들웨어를 작성하면 됩니다.

next()를 통해 넘어갈 수 있도록 반드시 적어줍시다.

(* 아래 미들웨는 JwtModule 에서 provider로 주입하고, Global Module로 만들었기 때문에 @Injectable()로 만들지는 않았습니다. 보통은 의존성 주입을할 수 있게 @Injectable로 만들어주곤하죠)

import { NestMiddleware } from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';

export class JwtMiddleWare implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(req.headers);
    next();
  }
}

 

Nest에서 미들웨어를 사용하기 위해서는 AppModule을 NestModule을 implements를 통해 연장한 다음 다음과 같이 구성해줍니다. path와 method를 통해 특정 라우트, 특정 메서드에서만 작동할수 있도록 할 수 있습니다.

Modules that include middleware have to implement the NestModule interface. 

 

NestModule은 다음과 같이 생겼습니다.

export interface NestModule {
    configure(consumer: MiddlewareConsumer): any;
}
* The configure() method can be made asynchronous using async/await (e.g., you can await completion of an asynchronous operation inside the configure() method body).

 

NestModule를 연장한 AppModule은 다음과 같이 사용할 수 있습니다.

/graphql 경로에서 POST 메서드 일때만 적용됩니다.

export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(JwtMiddleWare).forRoutes({
      path: '/graphql',
      method: RequestMethod.POST,
    });
  }
}

 

 

만약 Dependency Injection해서 사용하고 싶다면 @Injectable을 붙인 후에 모듈로 넣고, 사용하고자 하는 다른 모듈에 import하면 됩니다.

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    console.log('Request...');
    next();
  }
}
Dependency injection#

 

 

Global Middleware

AppModule이 아니라 main.ts에서 global middleware를 사용할 수 있습니다.

다음과 같이 사용합니다. 만약 미들웨어를 클래스형으로 작성하셨다면 사용하실 수 없습니다.

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

  // global validation pipe
  app.useGlobalPipes(new ValidationPipe());

  // global middleware
  app.use(JwtMiddleWare);

  await app.listen(PORT);
  console.log(`server on : http://localhost:${PORT}`);
}

 

 

Functional middleware

Injection 등의 기능을 필요로 하지 않는 간단한 미들웨어의 경우 함수 형태로 작성할수도 있다고 합니다.

NestMiddleware를 implements할 필요 없이 그냥 다음과 같이 작성하면 됩니다.

 

단, 이 방법을 사용하시면 후술할 Main.ts에서 global middleware로 사용할 수는 없습니다.

사용하게 되면 app.use() requires a middleware function 에러가 뜹니다. 함수로 쓰라는 거죠.

 

import { NextFunction, Request, Response } from 'express';

export function JwtMiddleWare(req: Request, res: Response, next: NextFunction) {
  console.log(req.headers);
  next();
}

 

 

wildcard를 이용한 pattern router

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

 

The 'ab*cd' route path will match abcd, ab_cd, abecd, and so on.

The characters ?, +, *, and () may be used in a route path, and are subsets of their regular expression counterparts. The hyphen ( -) and the dot (.) are interpreted literally by string-based paths.

 

The fastify package uses the latest version of the path-to-regexp package, which no longer supports wildcard asterisks *. Instead, you must use parameters (e.g., (.*), :splat*).

 

여기서 주의할 점은, express가 아니라 fasify를 사용할 경우 입니다. 

The fastify package uses the latest version of the path-to-regexp package, which no longer supports wildcard asterisks *. Instead, you must use parameters (e.g., (.*), :splat*).

 

 

Excluding routes

특정 경로의 특정 메서드에는 미들웨어를 적용시키고 싶지 않은 경우가 있습니다. exclude 메서드를 이용하면 됩니다.

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

 

 

Multiple middleware

다음과 같이 연속적으로 사용해서 여러 미들웨어를 사용할 수 있습니다.

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

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체