2

我想知道 grpc 服务中是否存在字段验证模式。

我知道 RpcException 具有元数据预告片属性,并且我可以添加有关我的错误的其他信息。

我的问题是:有一个要遵循的模式吗?如果不是,下面哪个例子会更符合预期。

示例 1:

Metadata trailers = new Metadata();
trailers.Add("Name", "is required");
trailers.Add("Age", "is required");
trailers.Add("Age", "must be over 21");
throw new RpcException(new Status(StatusCode.InvalidArgument, "Invalid Argument"), trailers, "One or more errors");

示例 2:

Metadata trailers = new Metadata();
trailers.Add("errors", @"{""Name"":[""Is required""],""Age"":[""Is required"",""must be over 21""]}");
throw new RpcException(new Status(StatusCode.InvalidArgument, "Invalid Argument"), trailers, "One or more errors");

我想接受此响应并在需要时使用 RFC 7807 规范将其转换为 json

4

1 回答 1

3

我不熟悉 C# API,但我可以谈谈 gRPC API,也许它可以帮助您实现 C#。

gRPC 错误模型 错误模型在逻辑上由google.rpc.Status定义,当发生 API 错误时,会返回一个实例给客户端。下面的代码片段展示了错误模型的整体设计,当出现问题时返回:

package google.rpc;

message Status {

  // A simple error code that can be easily handled by the client. The
  // actual error code is defined by `google.rpc.Code`.
  int32 code = 1;

  // A developer-facing human-readable error message in English. It should
  // both explain the error and offer an actionable resolution to it.
  string message = 2;

  // Additional error information that the client code can use to handle
  // the error, such as retry delay or any business possible errors
  repeated google.protobuf.Any details = 3;

}

您应该使用详细信息字段将额外信息传递给错误。例如,对于InvalidArgument,您应该传递带有字段违规的BadRequest对象

类似的东西(Golang 代码,希望它对你有意义)

st := status.New(codes.InvalidArgument, "invalid username")
v := &BadRequest_FieldViolation{
    Field: "username",
    Description: "The username must only contain alphanumeric characters",
}
br := &BadRequest{}
br.FieldViolations = append(br.FieldViolations, v)
st, _ := st.WithDetails(br)

是 gRPC 提供的对象列表,如果其中任何一个适合您的场景,您可以将其用作错误详细信息,您可以随时创建自己的。

在详细信息字段中返回与业务相关的内容是一种很好的做法。就像一个已知的错误代码。这样您的客户就可以对问题做出回应。

errorDetail := &BusinessError{
  ErrorCode: CODE,
  ErrorMessage: "Failed to filter hotel rooms",
}
st := status.New(codes.Internal, "Something went wrong :( ")
st, _ = st.WithDetails(errorDetail)
于 2020-08-04T15:08:26.647 回答