簡體   English   中英

從 gRPC ServerInterceptor 返回錯誤的正確方法是什么

[英]What is the proper way to return an error from gRPC ServerInterceptor

我有一個使用 gRPC 的 Quarkus 應用程序。 我已經實現了一個 ServerInterceptor 來查找和驗證身份驗證令牌。

@ApplicationScoped
public class GrpcAuthInterceptor implements ServerInterceptor {

    @Inject
    AuthenticationService authenticationService;

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
        String token = metadata.get(AuthenticationConstants.AUTH_HEADER_KEY);

        Context context = Context.current();

        if (!Strings.isNullOrEmpty(token)) {
            String fbToken = authenticationService.verifyIdToken(token);
            context = context.withValue(AuthenticationConstants.CONTEXT_FB_USER_KEY, fbToken);
        } else {
            serverCall.close(Status.UNAUTHENTICATED.withDescription("Auth Token Required"), metadata);
        }

        return Contexts.interceptCall(
                context,
                serverCall,
                metadata,
                serverCallHandler);
    }
}

這有效並像這樣向客戶端發送消息:

gRPC Error (code: 16, codeName: UNAUTHENTICATED, message: Auth Token Required, details: [], rawResponse: null, trailers: {})

但它在服務器上記錄了這個錯誤,因為我在發送錯誤后沒有從方法中返回:

2022-10-04 21:50:23,006 ERROR [io.qua.mut.run.MutinyInfrastructure] (vert.x-eventloop-thread-0)
Mutiny had to drop the following exception: java.lang.IllegalStateException: call is closed

一些帖子建議我可以像這樣返回一個空的 ServerCall.Listener:

serverCall.close(Status.UNAUTHENTICATED.withDescription("Auth Token Required"), metadata);
return new ServerCall.Listener<ReqT>() {};

這有效並消除了服務器端錯誤消息,但它破壞了返回給客戶端的消息。 客戶只是得到這個:

gRPC Error (code: 2, codeName: UNKNOWN, message: null, details: [], rawResponse: null, trailers: {})

所以我的問題是:如何向客戶端返回有意義的錯誤消息而不在服務器端記錄異常?

您可以在 try 塊中捕獲所有內容並在其中發送消息; 您面臨的問題是您在返回之前先關閉呼叫,因此它會嘗試處理已經關閉的 pipe。

在第二種情況下,當您在“關閉”消息之后立即發送“無效”消息時,詳細消息將被覆蓋。

嘗試類似的東西:

@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) 
{
    String token = metadata.get(AuthenticationConstants.AUTH_HEADER_KEY);
    Context context = Context.current();
    boolean mustClose=false;
    try
    {
       if (!Strings.isNullOrEmpty(token)) 
       {
           String fbToken = authenticationService.verifyIdToken(token);
           context = context.withValue(AuthenticationConstants.CONTEXT_FB_USER_KEY, fbToken);
           return Contexts.interceptCall(context,serverCall,metadata, serverCallHandler);
       } 
       else 
       {
           mustClose=true;
           return new ServerCall.Listener<ReqT>() {};
       }              
     } 
     finally 
     {
        if (mustClose)
             serverCall.close(Status.UNAUTHENTICATED.withDescription("Auth Token Required"), metadata);
     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM