[NestJS] Execution context

hahaha·2021년 9월 12일
1

NestJS

목록 보기
7/11
post-thumbnail

Excution context

NestJS Docs - Excution context

ArgumentsHost class

  • 핸들러에 전달되는 인수를 검색하는 메서드 제공
  • 접근하려는 위치에 host 매개변수로 참조되는 ArgumentsHost의 인스턴스 제공
  • HTTP 서버 애플리케이션의 경우,
    host 객체는 [request, response, next] 배열 캡슐화
  • GraphQL 애플리케이션의 경우,
    host 객체는 [root, args, context, info] 배열 캡슐화

Current application context

  • 현재 애플리케이션의 유형 결정
  • ArgumentsHostgetType() 메서드 사용
if(host.getType() === 'http') {
  // 생략
} else if (host.getType === 'rpc') {
  // 생략
} else if (host.getType === 'graphql') {
  // 생략
}

Host handler arguments

  • 핸들러에 전달되는 인수 배열 검색
  • host 객체의 getArgs() 메서드 사용
const [req, res, next] = host.getArgs();

// 인덱스를 이용해 특정 인수 가져오기
const req = host.getArgByIndex(0);
  • 인덱스 별로 요청 및 응답 객체하는 방식은
    애플리케이션을 특정 실행 컨텍스트에 연결하므로 권장하지 않음
    -> 애플리케이션 컨텍스트로 전환하여 사용
const ctx = host.switchToHttp();
const req = ctx.getRequest<Request>();
const res = ctx.getResponse<Response>();

// HTTP 외 애플리케이션
switchToRpc(): RpcArgumentsHost;
export interface RpcArgumentsHost {
  getData<T>(): T;
  getContext<T>(): T;
}

switchToWs(): WsArgumentsHost;
export interface WsArgumentsHost {
  getData<T>(): T;
  getClient<T>(): T;
}

ExecutionContext class

  • ArgumentsHost를 확장하여 현재 실행 프로세스에 대한 추가 세부 정보 제공
export interface ExecutionContext extends ArgumentsHost {
  // 특정 핸들러가 속한 Controller 클래스 타입 반환
  getClass<T>(): Type<T>;
  
  // 호출될 핸들러에 대한 참조 반환
  getHandler(): Function;
}

Reflection and metadata

Guards에서 사용되는 예제 보기(맥락 이해)

// cats.controller.ts
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}

// roles.guard.ts
const roles = this.reflector.get<string[]>('roles', context.getHandler());
  • Reflector#get(메타데이터 키, 컨텍스트(데코레이터 대상))
    - controller 메타데이터를 추출할 경우,
    두번째 인수로 context.getClass() 전달

  • 컨트롤러, 메서드에 모두 메타데이터가 첨부된 경우

// cats.controller.ts
@Roles('user')		// 컨트롤러 수준
@Controller('cats')
export class CatsController {
  @Post()
  @Roles('admin')	// 메서드 수준
  async create(@Body() createCatDto: CreateCatDto) {
    this.catsService.create(createCatDto);
  }
}

// roles.guard.ts

// 1. 컨트롤러 역할을 기본으로 하고, 특정 메서드에 대해 선택적으로 역할 재정의하려는 경우
const roles = this.reflector.getAllAndOverride<string[]>('roles', [
  context.getHandler(),
  context.getClass(),
]);

//2. 두 수준 모두에 대한 메타데이터를 가져와 병합하려는 경우
const roles = this.reflector.getAllAndMerge<string[]>('roles', [
  context.getHandler(),
  context.getClass(),
]);
profile
junior backend-developer 👶💻

0개의 댓글