從前面幾節我們可以發現,在NestJS中透過裝飾器,能對於我們想要針對某個class套用額外功能起到很有效的幫助,如果有內建裝飾器無法解決的問題,NestJS也提供了自訂裝飾器(Custom decorator)的功能
自訂裝飾器可以分成三種類型:
用 $ nest g decorator <DECORATOR_NAME>
預設產生的即為Metadata裝飾器
取得路由參數
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const User = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user?.[data] : user;
},
);
解釋說明:
1.使用createParamDecorator這個function產生的,參數使用工廠函式
2.工廠函式裡的兩個參數:data代表帶入這個裝飾器的值、ExecutionContext用來取得其他額外資訊
middleware中做假資料:
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class MockDataMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
req.role='staff';
req.user={name:'user1'}
next();
}
}
Api測試結果:
import { UseGuards, applyDecorators } from '@nestjs/common';
import { Roles } from '../roles/roles.decorator';
import { RoleGuard } from 'src/guards/role/role.guard';
export const Authorization = (...args: string[]) => applyDecorators(Roles(...args),UseGuards(RoleGuard));
解釋說明:
1.使用applyDecorators,裡面帶入要整合的裝飾器
2.第一個裝飾器Roles,裡面帶入我們要用的參數
3.第二個裝飾器UseGuards,裡面帶入RoleGuard
(回到app.controller.ts)
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { User } from './decorators/users/users.decorator';
import { Authorization } from './decorators/authorization/authorization.decorator';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Authorization('admin','staff')
@Get()
getHello(@User()user:any): any {
// return this.appService.getHello();
return user;
}
}
解釋說明: