I'm trying to use a "bad input exception filter" to catch errors and return them to the client. I have both websockets and http endpoints throughout my monorepo, on one application I have both.

The issue I'm having, I don't want to use two separate exception filters for WS & HTTP and until now I was relying on nestjs defining either the request or the socket context to tap into that and either return the error back to the websocket or returning the error via http res.send.

But it turns out they're both defined even when there's no websockets within the application at all, no adapter registered, nothing.

Exception handler:

    const req: IRequest = host.switchToHttp().getRequest();
    const res: Response = host.switchToHttp().getResponse();

    const socket: ISocket = host.switchToWs().getClient();
  

    if (req && res) {
     // returning req res
    }

    if (socket) {
      // emitting error on socket

Is there a way to either:

  • prevent this
  • tap into another value from the context to know where to return the error to

Thank you.

1

There are 1 answers

0
Jay McDoniel On

Something to take note of is that the ExecutionContext has an args property that is an array of values related to the request. The switchTo*().get*() methods are really just syntactic sugar for things like getArgsByIndex(). What you can do, instead of checking for truthiness of req, res, and socket is use the getType() property on the ArgumentHost/ExecutionContext which will return http, ws, rpc, or graphql depending on the request, and then you can separate out your error handling logic from there. I like to use a switch case for it, but if statements would work too

switch (host.getType<ContextType | 'graphql'>()) {
  case 'http':
    return this.handleHttpError(exception, host);
  case 'graphql':
    return this.handleGqlError(exception, host);
  case 'ws':
    return this.handleWsError(exception, host);
  case 'rpc':
    return this.handleRpcError(exception, host);
}

I have something similar in an interceptor for logging, using ExecutionContext instead of ArgumentHost, but the idea should be the same. ExecutionContext just has a getClass and getHandler method