Papooch / nestjs-cls

A continuation-local storage (async context) module compatible with NestJS's dependency injection.
https://papooch.github.io/nestjs-cls/
MIT License
393 stars 23 forks source link

Suport for a global interceptor or other idea #52

Closed andremartinsds closed 1 year ago

andremartinsds commented 1 year ago

Hi folks, in this library we have an opportunity to write an interceptor to use on the controller, what do you think about making a globalClsInterceptor? is it possible?

sometimes the interceptor doesn't work very well, I think we do not have an injection of ClsService in the current interceptor when we do not use it on the same module, I'm not totally sure and confident about it.

I have one situation in my application to use that, but I think if I put the if condition to verify the ClsService on interceptor probably it will return an undefined value and not work so well.

In this application we do not have a bootstrap function, because it is a library and we will put it in other projects, I test the Cls library in one full project NestJs with dependencies like the documentation and it works fine.

Now I will write the sample, the minimal example:

The service

@Injectable()
export class LoggerService {
  constructor(private readonly cls: ClsService) {}

  private addIp(param: string): void {
      param = this.cls.get('ip');
  }
}

The interceptor:

@Injectable()
export class IpInterceptor {
  // I put it that way but if I change for standard of documentation it produces the same error
  constructor(private readonly cls?: ClsService) {
    if (!(cls instanceof ClsService)) {
      this.cls = ClsServiceManager.getClsService();
    }
  }
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();

    request.setHeader('ip', ''ip-bla-bla-bla');
    this.cls.set('ip', request.headers['ip']);
    return next.handle();
  }
}

The Module:

@Module({
  imports: [
    ClsModule.forRoot({
      global: true,
      middleware: { mount: true },
    }),
  ],
  providers: [LoggerService],
  exports: [LoggerService],
})
export class NewClsModule {}

And now I will use it in other applications, (e.g: another nest application):

@Module({
  imports: [
    NewClsModule
  ],
  providers: [],
  exports: [],
})
export class InfraModule {}

And add the interceptor to the bootstrap function


app.useGlobalInterceptors(new IpInterceptor());

And I receive the following error:

Nest can't resolve dependencies of the ClsModule (?, ModuleRef). Please make sure that the argument HttpAdapterHost at index [0] is available in the ClsModule context.

In my case, I need this approach because I use a global log and need a global interceptor.

Thank you for your answers ;)

Papooch commented 1 year ago

This seems like the exact same issue as in #51. I'll look into it later, but please verify that the @nestjs/* dependencies in the library code are actually peer dependencies.