繁体   English   中英

如何捕获验证错误消息 - Nestjs 网关 Socket.io

[英]How to catch validation error message - Nestjs Gateway Socket.io

我有一个验证 pipe 检查用户发送的 JSON 数据是否有效。 验证器运行良好,但我无法捕获错误然后将其发送给客户端。 我知道ValidationPipe构造函数中的exeptionFactory属性,但我仍然无法捕获错误并且它仍然在控制台中登录。

[Nest] 11820  - 01/07/2023, 11:12:25 PM   ERROR [WsExceptionsHandler] Bad Request Exception
BadRequestException: Bad Request Exception

这是一个代码

  @SubscribeMessage(Stream.Transactions)
  @UseGuards(JwtAuthGuard)
  @UsePipes(new ValidationPipe())
  handleTransactions(
    clien: any,
    @MessageBody() data: TransactionObject,
  ) {
    let req = this.streamService.transaction(data)
    return { event: Stream.Transactions, data: req }
  }

我认为您可以创建一个过滤器来获取错误并返回一些特定数据。 但是您可以通过几种方式做到这一点:创建一个Websocket 异常过滤器来捕获错误或使用您在问题中提到的exceptionFactory生成WsException并捕获到过滤器中。

主要问题(如果我没记错的话)是 pipe 不返回WsException而是BadRequestException

所以要使用异常过滤器,异常是Bad Request ,你可以使用这个:

@Catch(BadRequestException)
export class BadRequestExceptionsFilter extends BaseWsExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    // Here you have the exception and you can check the data
    const wsException = new WsException(exception.getResponse())
    super.catch(wsException, host);
  }
}

请注意此代码如何遵循文档

现在您不仅可以获取和读取异常,还可以创建一个正确的WsException

要使用它,您可以将@UseFilters(BadRequestExceptionsFilter)添加到您的网关中。

另一种方法是捕获 WS 和 HTTP 异常并正确处理你想要的,类似于这个例子 这个想法可以是捕获 HTTP 异常只是为了得到Bad Request所以你想要的上下文将始终是WS

@Catch(WsException, HttpException)
export class WsAndHttpExceptionFilter {
  public catch(exception: HttpException, host: ArgumentsHost) {
    // Here you have the exception and you can check the data
    const ctx = host.switchToWs()
    const client = ctx.getClient() as WebSocket;
    client.send(JSON.stringify({ /* ... */ }))
  }
}

或者您也可以尝试创建exceptionFactory以返回WsException

  • 进入装饰器:
@UsePipes(new ValidationPipe({
    exceptionFactory(validationErrors: ValidationError[] = []) {
        // Here are the errors
        if (this.isDetailedOutputDisabled) {
          return new WsException();
        }
        const errors = this.flattenValidationErrors(validationErrors);
        return new WsException(errors);
    }
}))

检查工厂如何进入项目以及此代码如何尝试遵循相同的方式但返回WsException

  • 或者在 class 扩展ValidationPipe中:
@Injectable()
export class WSValidationPipe extends ValidationPipe {
  createExceptionFactory() {
    return (validationErrors: ValidationError[] = []) {
        // Here are the errors
        if (this.isDetailedOutputDisabled) {
          return new WsException();
        }
        const errors = this.flattenValidationErrors(validationErrors);
        return new WsException(errors);
    }
  }
}

顺便说一句,你也可以@Catch(WsException) (而且只有这个异常更清楚)被抛出一次,如果它对你返回你想要的数据是有用的:

@Catch(WsException)
export class WebsocketExceptionsFilter extends BaseWsExceptionFilter { 
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToWs()
    const client = ctx.getClient() as WebSocket;
    const data = ctx.getData();
    client.send(JSON.stringify({
      event: 'error',
      ok: false,
      error: exception.getError(),
      data: data  // Or whatever you want to add
    }))
  }
}

我现在无法测试所有这些代码,但我已经使用了其中一些片段并且对我有用,希望它有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM