Controller
HTTP Requestを処理するやつ
@Controller()
をクラス定義前に付ける@Controller('cats')
export class CatsController {上記の例は
/cats
がパスになるGETメソッドの定義
@Get()
findAll(): string {
return 'This action returns all cats';
}@Get('breed')
だとパスは/cats/breed
になる
Provider
Service
,Respository
,Factory
,Helper
などの総称Provider
はModule
に登録すると使える@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class AppModule {}
Service
DBなどからデータをとってくるやつ
@Injectable()
をクラス定義に付ける@Injectable()
export class CatsService {Controller
のコンストラクタの引数にすればインスタンスを注入できる@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
Module
アプリを構造化するやつ
@Module
をクラス定義につける@Module({
controllers: [CatsController],
providers: [CatsService],
imports: [...],
exports: [...],
})
export class CatsModule {}
MiddleWare
HTTPリクエストの処理の前に付けるやつ
関数でもクラスでも作成できる
クラスの例
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log('Request...');
next();
}
}Module
のconfigure
メソッドで注入できる@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware) // Middlewareを登録
.forRoutes('cats'); // `/cats`パスにMiddlewareを適用
}
}forRoutes
にController
を渡してもよい.forRoutes(CatsController);
Fuctional middleware
の例次の引数も持ったただの関数
export function logger(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
};以下のように適用する
consumer
.apply(logger)
.forRoutes(CatsController);
Pipe
Route handler
の引数に適用して、引数の変換やバリデーションを行うやつビルトインの
ParseIntPipe
の使用例@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}インスタンス化を自分ですることもできる
@Get(':id')
async findOne(
@Param('id', new ParseIntPipe({ errorHttpStatusCode: HttpStatus.NOT_ACCEPTABLE }))
id: number,
) {
return this.catsService.findOne(id);
}Pipe
の処理が失敗すると例外を投げるCustom pipe
の例@Injectable()
export class ValidationPipe<T, R> implements PipeTransform<T, R> {
transform(value: T, metadata: ArgumentMetadata): R { // 必須メソッド
return convert(value);
}
}value
はPipe
を適用する関数の引数ArgumentMetadata
は以下の情報を持っているexport interface ArgumentMetadata {
type: 'body' | 'query' | 'param' | 'custom';
metatype?: Type<unknown>;
data?: string;
}
Guard
Route handler
の前に作用して、そのRoute handler
を実行するかしないかを決定するやつMiddleware
に比べて、どのRoute handler
に適用されるのか詳細に設定できるよく認証の確認に使われる
@Injectable()
export class AuthGuard implements CanActivate {
// 必須のメソッド
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}Guard
の適用@Controller('cats')
@UseGuards(RolesGuard)
export class CatsController {}@UseGuards
はController
内のメソッドにも適用できるGuard
内で対象のRoute handler
に付けられたdecorator
を参照することが可能Route handler
に付けるCustom decorator
の作成:export const Roles = Reflector.createDecorator<string[]>();
Roles
をRoute handler
に適用する:@Post()
@Roles(['admin'])
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}Roles
をGuard
から参照する:@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
// ExecutionContextからRolesを取得できる
const roles = this.reflector.get(Roles, context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return matchRoles(roles, user.roles);
}
}
Interceptor
Route handler
の前後に処理を挟むことができるやつNestInterceptor
を継承するintercept()
メソッドを実装するintercept()
メソッドの引数はExecutionContext
とCallHandler
の2つCallHandler
はRoute handler
のことintercept()
メソッドの中でCallHandler
を実行しないと、Route handler
は実行されないLoggingInterceptor
の例@Injectable()
export class LoggingInterceptor implements NestInterceptor<T, R> {
intercept(context: ExecutionContext, next: CallHandler): Observable<R> {
console.log('Before...');
const now = Date.now();
return next
.handle() // Observale<T>
.pipe(
tap(() => console.log(`After... ${Date.now() - now}ms`)),
);
}
}Interceptor
の適用@UseInterceptors(LoggingInterceptor)
export class CatsController {}メソッドレベルにも適用できる