salt-pepper
salt-pepper

Reputation: 125

Access or pass variables to a interceptor in NestJS

I am new to NestJS and have been looking at a couple of solutions but haven't found a way. My API returns list of users, the users are either read from the cache if present or from the DB and based on this I need to set the headers. I want the interceptor to handle this part.

My Controller

  @UseInterceptors(CacheOrServiceHeaderInterceptor)
  @Get('users')
  public async users(
      @Query('id') clinicianId: number,
      @Query('name') specialtyName: string,
  ){
    const setFlags: MetaFlags = {setCacheHeader: false, setServiceHeader: false};

    const data = await this.service.getUsers(id, name, setFlags);
    return data;
}

My service class

export interface MetaFlags {
  setServiceHeader: boolean
  setCacheHeader?: boolean,
}
:
:
public async getUsers(....){
// code that handles whether cache is used or a service is used to get users
 and based on it, the metaFlags are set. setCacheHeader = true if read from cache or setServiceHeader = true if read from DB.

My interceptor looks like this

@Injectable()
export class CacheOrServiceHeaderInterceptor implements NestInterceptor {
  
    public intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
       
        return next
            .handle()
            .pipe(
                map((data) => {
                    const req = context.switchToHttp().getRequest();
    // this is static but I want a condition here if 
                    if(MetaFlags.setCacheHeader)
                    // set xyz header
                     else set abc header
                    req.res.set('x-api-key', 'pretty secure');
                    return data;
                }
                 
            )
        );}}

Is there a way to pass these flags to the interceptor or make the interceptor read these flag values ?

Upvotes: 2

Views: 4985

Answers (1)

Jay McDoniel
Jay McDoniel

Reputation: 70191

I would suggest returning what header should be set as a part of the service of controller's return. If you end up using a global state, you could get multiple requests to the endpoint overwriting the global state before you read it in the interceptor and send back the wrong header. Something like

{
  data: regularDataHere,
  header: 'cache' || 'database'
}

Now in the map of your interceptor, you can read the data object and pull off the data property to return only it and not expose this header field to the client, and read the header field so you know which header to set on the response. Something like this:

@Injectable()
export class CacheOrServiceHeaderInterceptor implements NestInterceptor {
  
    public intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handler().pipe(
      map((data: { data: DataType, header: 'cache' | 'database' }) => {
        const res = context.switchToHttp().getResponse<ResponseType>();
        if (data.header === 'database') {
          res.setHeader('x-api-key', 'pretty secure');
        } else {
          res.setHeader(xyz, value);
        }
        return data.data;
      })
    );
  }
}

Upvotes: 1

Related Questions