我有一个像这样的自定义方法装饰器。
export function CustomDecorator() {
return applyDecorators(
UseGuards(JwtAuthGuard)
);
}
在自定义装饰器中,我想获取请求头但不知道如何获取请求实例?
您将无法在类或方法装饰器中获取
ExectuionContext
对象或 Request
对象,因为这些装饰器在导入时立即运行。相反,应该做的是制作一个确实具有可用的 SuperGuard
的 ExecutionContext
。这个 SuperGuard
应该通过 constructor
将所有其他守卫注入其中,并且根据标头,您应该调用/返回所调用守卫的结果。像这样的东西:
@Injectable()
export class SuperGuard implements CanActivate {
constructor(
private readonly jwtAuthGuard: JwtAuthGuard,
private readonly googleAuthGuard: GoogleAuthGuard,
) {}
canActivate(context: ExecutionContext) {
const req = context.switchToHttp().getRequest();
if (req.headers['whatever'] === 'google') {
return this.googleAuthGuard.canActivate(context);
} else {
return this.jwtAuthGuard.canActivate(context);
}
}
}
我设法使用装饰器工厂内的
Inject
访问装饰器内的执行上下文。
这是我的装饰器,它吞下方法产生的错误并在发生异常时返回预定义的值。
import { Injectable, Scope, Inject, ExecutionContext } from '@nestjs/common';
import { CONTEXT } from '@nestjs/graphql';
@Injectable({ scope: Scope.REQUEST })
export class ExceptionsHandler {
public constructor(@Inject(CONTEXT) private readonly context: ExecutionContext) {}
private integrationsRequestErrors: unknown[] = [];
public handle(error: unknown): void {
// ADD error to context if necessary
this.integrationsRequestErrors.push(error);
}
}
export const ErrorSwallower = (options: {
serviceImplementation: string;
defaultValue: unknown;
errorMessage?: string;
}): MethodDecorator => {
const { defaultValue, integration } = options;
const Injector = Inject(ExceptionsHandler);
return (target: object, _propertyKey: string, descriptor: PropertyDescriptor) => {
Injector(target, 'exceptionsHandler');
const originalMethod = descriptor.value;
descriptor.value = function (...args: unknown[]) {
const exceptionHandler = this.experiment as ExceptionsHandler;
try {
const result = originalMethod.apply(this, args);
if (result && result instanceof Promise) {
return result.catch((error: unknown) => {
exceptionHandler.handle({ error, integration });
return defaultValue;
});
}
return result;
} catch (error) {
exceptionHandler.handle({ error, integration });
return defaultValue;
}
};
};
};
这是上面的代码的实际应用:
@Injectable()
export class ExampleService {
@ErrorSwallower({ serviceImplementation: 'ExampleClass', defaultValue: [] })
private async getSomeData(args: IGetSomeDataArgs): Promise<ISomeData[]> {
throw new Error('Oops');
}
}
Я поступаю следующим образом:
constructor(@Inject(CONTEXT) private readonly context: ExecutionContext) {}
export function CustomDecorator() {
return applyDecorators(
UseGuards(JwtAuthGuard)
const context = this.context;
);
}