StreamingHttpServiceFilter 的 ServiceTalk gRPC 错误代码映射

ServiceTalk gRPC error code mapping for StreamingHttpServiceFilter

我们已经实现了 StreamingHttpServiceFilter 对每个请求执行身份验证。

在身份验证不成功时,我们使用以下代码 return 401 未授权错误:

private StreamingHttpResponse createUnauthorizedResponse(final StreamingHttpResponseFactory responseFactory) {
        return responseFactory.unauthorized();
    }

当过滤器 return 出错时,在客户端我们收到以下消息

GrpcStatus{code=INTERNAL, cause=null, description='HTTP status code: 401 Unauthorized invalid content-type: null headers: NettyH2HeadersToHttpHeaders[transfer-encoding: ]'}

如您所见,GrpcStatus 有 code=INTERNAL,这意味着客户端需要解析 description,并找出错误代码。

是否可以在准备来自过滤器的响应时添加任何额外的元数据,以便代码可以是 UNAUTHENTICATED 或者是否有任何可用的客户端实用程序读取描述并转换为 http 状态代码?

gRPC 协议不太关注 HTTP 响应状态码,它总是期望 200 OK。其他状态代码将映射到 INTERNAL gRPC 代码。相反,它依赖于 HTTP/2 响应消息的 grpc-statusgrpc-message 作为尾部(或 headers,当没有负载 body 时)。请参阅 gRPC over HTTP2 文档中的 Responses 部分。

当您处于 HTTP 级别并编写 StreamingHttpServiceFilter 时,您负责根据 gRPC 协议生成响应。最小响应是 Trailers-Only 并包含 HTTP-Status Content-Type Status [Status-Message] *Custom-Metadata.

对于所描述的 use-case,手动生成适当的响应应该很容易。

另一种方法是从 gRPC 级别抛出 GrpcStatusException:从服务端点或 gRPC-filter。然后 ServiceTalk 将该异常映射到适当的 HTTP/2 响应,其中包含所有必需的 header 字段。

// Throws GrpcStatusException:
throw new GrpcStatus(GrpcStatusCode.UNAUTHENTICATED, null, "Your message for the client")
        .asException();

但是,在您的情况下,通过 AsyncContext 将身份验证信息从 StreamingHttpServiceFilter 级别传输到 gRPC-filter 可能会更加复杂。可能不值得。