Know Socket.io event name when handling an error on NestJS WebSocketGateway

Viewed 353

Let's say I have the following WebSocketGateway in NestJS

@WebSocketGateway()
export class MyWsGateway {
  @SubscribeMessage('my-event')
  @UserFilters(new MyWsExceptionFilter())
  create(@MessageBody() body: any) {
    throw new WsException('Forced error');
  }
}

At this point I want to customize the response to the client when an error occurs so I have implemented my own WsExceptionFilter based on NestJS official code (note this code is simplified):

@Catch(WsException)
export class MyWsExceptionFilter extends BaseWsExceptionFilter {
  handleError<TClient extends { emit: Function }>(
    client: TClient,
    exception: WsException
  ) {
    const message = {status: 'error', message: exception.getError()};
    client.emit('here-is-where-i-would-like-to-set-the-event-name', message);
  }
}

As you can see on the implementation of BaseWsExceptionFilter the response of the error is emited through event 'exception'. This is not valid for my case, though.

After long time searching on the Internet and surfing in NestJS's code, I haven't been able to find a way to get/know the input event name where the error was thrown.

Any ideas?

1 Answers

Nestjs attach metadata on function using decorators, including the event name you are looking for. You can access those metadata using Reflect.getMetadata(...).

So if you have a reference to the event handler method wich throw the exception you can get the message name like this : const messageName = Reflect.getMetadata("message", methodReference)

To get the reference to the handler method, you can use a nestjs interceptor.

async intercept(context, next) {
    return next.handle().pipe(tap({
        error: (err)=> {
            err.eventName = Reflect.getMetadata(
                'message', 
                (context.switchToWs() as any).handler
            )
        }
    })
}

Then in your exception filter, you can access the event name !

Related