nest icon indicating copy to clipboard operation
nest copied to clipboard

Not throwing the exception/error when using ws adapter websocket

Open SairamPotta opened this issue 2 years ago • 5 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Current behavior

When I am trying to throw the exception/error on conditional basis on websocket it is not sending any handshake to the client.

here is the simple code

import WebSocket from 'ws';
import {
  SubscribeMessage,
  WebSocketGateway,
  WsException,
} from '@nestjs/websockets';

@WebSocketGateway({ path: '/api' })
export class MainGateway {
  @SubscribeMessage('message')
  handleMessage(client: WebSocket, payload: any) {
    if (payload.id === 4) {
      throw new WsException('not Found');
    }

    client.send(JSON.stringify({ id: payload.id }));
  }
}

I have just investigated why not throwing error found issue in this file https://github.com/nestjs/nest/blob/master/packages/websockets/exceptions/base-ws-exception-filter.ts#L33 https://github.com/nestjs/nest/blob/master/packages/websockets/exceptions/base-ws-exception-filter.ts#L41

For ws - websocket adapter emit method is not working.

Minimum reproduction code

https://codesandbox.io/s/admiring-hugle-o8wqf?file=/src/Event/event.gateway.ts

Steps to reproduce

No response

Expected behavior

Should throw the handshake error or close the web socket.

Package

  • [ ] I don't know. Or some 3rd-party package
  • [ ] @nestjs/common
  • [ ] @nestjs/core
  • [ ] @nestjs/microservices
  • [ ] @nestjs/platform-express
  • [ ] @nestjs/platform-fastify
  • [ ] @nestjs/platform-socket.io
  • [X] @nestjs/platform-ws
  • [ ] @nestjs/testing
  • [X] @nestjs/websockets
  • [ ] Other (see below)

Other package

No response

NestJS version

No response

Packages versions

"@nestjs/common": "^8.0.0",
    "@nestjs/core": "^8.0.0",
    "@nestjs/platform-express": "^8.0.0",
    "@nestjs/platform-ws": "^8.2.6",
    "@nestjs/websockets": "^8.2.6",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^7.2.0",
    "uuid": "^8.3.2",
    "ws": "^8.4.2"

Node.js version

No response

In which operating systems have you tested?

  • [X] macOS
  • [X] Windows
  • [ ] Linux

Other

No response

SairamPotta avatar Jan 29 '22 18:01 SairamPotta

Any updates on this issue. Please provide the solution or alternative way to handle this.

SairamPotta avatar Feb 08 '22 11:02 SairamPotta

Hi, it's working but needs more testing. If you find a bug, please report it.

import { ArgumentsHost, Catch } from '@nestjs/common';
import { BaseWsExceptionFilter } from '@nestjs/websockets';
import { PacketType } from 'socket.io-parser';

@Catch()
export class AllExceptionsSocketFilter extends BaseWsExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const client = host.switchToWs().getClient();
    client.packet({
      type: PacketType.ACK,
      data: [{ error: exception?.message }],
      id: client.nsp._ids++,
    });
  }
}

EDIT: New method, working and tested:

import { ArgumentsHost, Catch } from '@nestjs/common';
import { BaseWsExceptionFilter } from '@nestjs/websockets';

@Catch()
export class AllExceptionsSocketFilter extends BaseWsExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const args = host.getArgs();
    // event ack callback
    if ('function' === typeof args[args.length - 1]) {
      const ACKCallback = args.pop();
      ACKCallback({ error: exception.message, exception });
    }
  }
}

wilywork avatar Jan 18 '23 12:01 wilywork

this answer worked for me better

https://stackoverflow.com/a/62507382/11109259

@wilywork methods to find the acknowledgement methods fail sometimes

abdelhalim97 avatar Feb 06 '24 10:02 abdelhalim97

My ack callback (3rd Argument) is undefined, has anybody experienced this too?

adshrc avatar Feb 17 '24 14:02 adshrc

realy, ACK is not always the last parameter, so I made this correction, my current code:

import { ArgumentsHost, Catch } from '@nestjs/common';
import { BaseWsExceptionFilter } from '@nestjs/websockets';

@Catch()
export class AllExceptionsSocketFilter extends BaseWsExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const args = host.getArgs();
    // event ack callback
    const ACKCallback = args.reverse().find(a => 'function' === typeof a);
    if (ACKCallback) {
      ACKCallback({ error: exception.message, exception });
    }
  }
}

wilywork avatar Feb 23 '24 16:02 wilywork