NestJs将GRPC异常转换为HTTP异常

时间:2020-02-17 17:40:19

标签: javascript nestjs nestjs-gateways

我有一个通过GRPC连接到网关的HTTP服务器。网关还连接到其他网关。 GRPC微服务。流程如下所示:

客户端-> HttpServer-> GRPC服务器(网关)-> GRPC微服务服务器X

我目前处理错误的方式是这样的(请告诉我是否有更好的做法),为了简洁起见,我只会显示nessaccery代码

GRPC微服务服务器X

  @GrpcMethod() get(clientDetails: Records.UserDetails.AsObject): Records.RecordResponse.AsObject {
    this.logger.log("Get Record for client");
    throw new RpcException({message: 'some error', code: status.DATA_LOSS})
  }

这个简单的方法会向GRPC客户端抛出一个错误(可以正常工作)

GRPC服务器

  @GrpcMethod() async get(data: Records.UserDetails.AsObject, metaData): Promise<Records.RecordResponse.AsObject> {
    try {
      return await this.hpGrpcRecordsService.get(data).toPromise();
    } catch(e) {
      throw new RpcException(e)
    }
  }

Grpc服务器捕获到错误,而该错误又被捕获,请购买全局异常处理程序(这很好)

@Catch(RpcException)
export class ExceptionFilter implements RpcExceptionFilter<RpcException> {
  catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
    if( Object.prototype.hasOwnProperty.call(exception, 'message') && 
        Object.prototype.hasOwnProperty.call(exception.message, 'code') &&
        exception.message.code === 2
    ){ 
        exception.message.code = 13
    }

    return throwError(exception.getError());
  }
}

这会将错误返回给Http服务器(grpc客户端,可以正常工作)

现在,当它到达Http服务器时,我希望我可以设置另一个RPC异常处理程序,并将错误转换为HTTP除外。但我不确定是否可行,我只使用过Nest几天,但尚未完全了解它。

这里是我希望做的一个例子(代码不起作用,只是我想要的例子)。 id更喜欢全局捕获异常,而不是到处都有try / catch块

@Catch(RpcException)
export class ExceptionFilter implements RpcExceptionFilter<RpcException> {
  catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
    //Map UNKNOWN(2) grpc error to INTERNAL(13)
    if( Object.prototype.hasOwnProperty.call(exception, 'message') && 
        Object.prototype.hasOwnProperty.call(exception.message, 'code') &&
        exception.message.code === 2
    ){  exception.message.code = 13 }

    throw new HttpException('GOT EM', HttpStatus.BAD_GATEWAY)
  }
}

1 个答案:

答案 0 :(得分:2)

我已经被困在同一个地方一段时间了。看来可行的是,只有您作为消息发送的字符串才在HTTP服务器上收到。 因此,下面的代码可以用作HTTP服务器中的过滤器,但是您必须通过消息字符串检查状态。

@Catch(RpcException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: RpcException, host: ArgumentsHost) {

    const err = exception.getError();
    // console.log(err);
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();
    response
      .json({
        message: err["details"],
        code: err['code'],
        timestamp: new Date().toISOString(),
        path: request.url,
      });
  }
}
 if(err['details'] === UserBusinessErrors.InvalidCredentials.message){
 this.logger.error(e);
     throw new HttpException( UserBusinessErrors.InvalidCredentials.message, 409)
 } else {
     this.logger.error(e);
     throw new InternalServerErrorException();
 }