can we have a Throttle method decorator with access to the injectable instance?
Opened this issue · 1 comments
ticmaisdev commented
Is there an existing issue that is already proposing this?
- I have searched the existing issues
Is your feature request related to a problem? Please describe it
I'm assuming we can only set @Throttle
options before compile time since this decorator doesn't have access to the @Injectable
instance.
Describe the solution you'd like
I would like to have something like this:
/**
* This is a custom method decorator which is used to limit the rate
* at which a function can fire.
*
* This is going to override specific throttler configurations, at the specific method.
*
* @template T - The type of the instance.
*
* @param {Function} cb - A callback that provides the instance class with injected services,
* so it's possible to set throttle options at run time.
*/
export const Throttle = <T>(
cb: (instance: T) => Record<string, ThrottlerMethodOrControllerOptions>,
) => {
return function (
target: T,
propertyKey: string,
descriptor: PropertyDescriptor,
) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const throttleOptions = cb(this);
NestThrottle(throttleOptions)(
target,
propertyKey,
descriptor,
);
return originalMethod.apply(this, args);
};
return descriptor;
};
};
@Injectable()
export class MyController {
readonly config: EnvironmentVariables;
constructor(
private readonly configService: ConfigService<InferEnvironmentVariables>,){
const config = { ...this.configService.getOrThrow('all', { infer: true }) };
this.config = config;
}
@Throttle<MyController>((instance) => ({
default: {
limit: instance.config.rps.upload,
ttl: 1000,
}
}))
async upload(/* omitted */): Promise<any> {
/* omitted */
}
}
Teachability, documentation, adoption, migration strategy
I'm aware this decorator can be improved.
What is the motivation / use case for changing the behavior?
I've got a default throttling rule that applies to all routes, but some routes need specific options due to security issues. Although, as of now, it's not possible to set these rules dynamically.
With described solution we can dynamically set these options and comply with https://12factor.net. This would allow us to change throttling rules without the need to re-compile the app.
ticmaisdev commented
Another approach could be @PickThrottle('default')
or @PickThrottle('foobar')
.