第一个GRPC拦截器中的访问消息请求在第二个GRPC拦截器中的标头之前

2022-04-03 00:00:00 grpc java grpc-java

我的问题类似于this帖子,但它似乎很旧且处于非活动状态,因此我在此重新发帖。

基本上,我有一个奇怪的用例,我需要在GRPC请求正文(而不是头)中发送我的授权令牌。我的想法是使用一组拦截器,其中第一个拦截器将读取GRPC消息,并根据消息中的令牌设置Authorization头。第二个拦截器将是使用的普通授权拦截器,它将读取刚刚设置为Authorization头的令牌。我希望这样做,因为这将允许我重用已经存在的授权拦截器代码。

我这样调用拦截器:

ServerInterceptors.intercept(
    new MyResource(resource),
    new SecondInterceptorHeaderAuthorization(),
    new FirstInterceptorReadTokenFromMessageBody()
)

其中FirstInterceptorReadTokenFromMessageBody()如下所示:

public class FirstInterceptorReadTokenFromMessageBody implements ServerInterceptor {

  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {


    return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(
            next.startCall(call, headers)) {
          @Override
          public void onMessage(ReqT request) {

            var value = ((MyRequest) request).getAuthorization();
            Metadata.Key<String> key =
                Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER);
            headers.put(key, value);

            super.onMessage(request);
          }
        };
  }
}

SecondInterceptorHeaderAuthorization()拦截器:

public class SecondInterceptorHeaderAuthorization implements ServerInterceptor {

  public <ReqT, RespT> Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
      .... handle authorization here
}
拦截器只是以相反的顺序正确触发;请求最终由SecondInterceptorHeaderAuthorization()使用头授权处理,然后由FirstInterceptorReadTokenFromMessageBody()处理。如何让消息拦截器先运行,然后再运行头拦截器?这有可能吗?有没有更好的方法来解决我错过的这个问题?


解决方案

我想出来了。基本上,我遵循了帖子here

中描述的内容

我的FirstInterceptorReadTokenFromMessageBody类现在如下所示:

public class FirstInterceptorReadTokenFromMessageBody implements ServerInterceptor {
  @Override
  public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {

    final Listener<ReqT> authorizationLookUpCallListener =
        new ForwardingServerCallListener<ReqT>() {
          private final Listener<ReqT> NOOP = new Listener<ReqT>() {};
          private Listener<ReqT> delegate = NOOP;

          @Override
          protected Listener<ReqT> delegate() {
            return delegate;
          }

          @Override
          public void onMessage(ReqT message) {
            // ensures that this interceptor only run first
            if (delegate == NOOP) {
              if (message instanceof MyRequest) {
                String auth_token = ((MyRequest) message).getAuthToken();
                headers.put(
                    Metadata.Key.of("my-auth-token-header", Metadata.ASCII_STRING_MARSHALLER),
                    auth_token);
              }
              delegate = next.startCall(call, headers);
            }
            super.onMessage(message);
          }
        };

    ServerCallHandler<ReqT, RespT> handler =
        (call1, headers1) -> {
          call1.request(1);
          return authorizationLookUpCallListener;
        };

    return handler.startCall(call, headers);
  }
}

相关文章