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);
'Node, Nest, Deno > 🦁 Nest.js' 카테고리의 다른 글
Custom param decorators (0) | 2020.11.24 |
---|---|
Guard + MetaData (0) | 2020.11.24 |
dynamic-modules 만들기 (0) | 2020.11.24 |
dotenv 대신 @nestjs/config을 사용해야하는 이유 + 활용 (0) | 2020.11.21 |
DTO를 통한 검증을 위한 Pipe (Class Validator + mapped-types ...) (0) | 2020.11.19 |