基于输入值的gRPC响应标头

时间:2019-07-20 10:42:09

标签: java header grpc interceptor grpc-java

我需要根据传入的值发送gRPC请求的响应标头。做到这一点的方法是使用ServerInterceptor。但是这里有点卡住了。我可以使用ForwardingServerCallListener.SimpleForwardingServerCallListener#onMessage截取传入的值,但是我看不到将这个值放入上下文并在ForwardingServerCall.SimpleForwardingServerCall#sendHeaders中读取它的方法。

这是我的代码:

public class FooInterceptor implements ServerInterceptor {

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        var serverCall = new ForwardingServerCall.SimpleForwardingServerCall<>(call) {
            @Override
            public void sendHeaders(Metadata headers) {
                //Here I should get the value from the context and add it to the headers
                //var foo = CONTEXT_KEY.get("foo");
                //headers.put(METADATA_KEY, foo);
                super.sendHeaders(headers);
            }
        }
        ServerCall.Listener<ReqT> listenerWithContext = Contexts
                .interceptCall(Context.current(), serverCall, headers, next);
        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(listenerWithContext) {
            @Override
            public void onMessage(ReqT message) {
                if (message instanceof FooRequest) {
                    var foo = ((FooRequest) message).getFoo();
                    //How to add it to context?
                }
                super.onMessage(message);
            }
        };
    }
}

所以问题出在方法ForwardingServerCallListener.SimpleForwardingServerCallListener#onMessage上,我可以从消息中获取值,但无法用新值重写上下文。 任何想法/建议都将不胜感激!

1 个答案:

答案 0 :(得分:1)

我找到了一种解决方法,它不是最优雅的解决方案,但它似乎有效。由于尚无其他答案,将在此处发布。

我设法使用请求标头传递值。 因此,在ForwardingServerCallListener.SimpleForwardingServerCallListener#onMessage中,将值设置为请求标头,并在ForwardingServerCall.SimpleForwardingServerCall#sendHeaders内,将请求标头中的值写入该值并将其写入响应标头。

代码如下:

public class FooInterceptor implements ServerInterceptor {

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        var serverCall = new ForwardingServerCall.SimpleForwardingServerCall<>(call) {
            @Override
            public void sendHeaders(Metadata responseHeaders) {
                var foo = headers.get(Metadata.Key.of("x-value"), Metadata.ASCII_STRING_MARSHALLER));
                responseHeaders.put(Metadata.Key.of("x-value"), Metadata.ASCII_STRING_MARSHALLER), foo);
                super.sendHeaders(responseHeaders);
            }
        }
        ServerCall.Listener<ReqT> listenerWithContext = Contexts
                .interceptCall(Context.current(), serverCall, headers, next);
        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<>(listenerWithContext) {
            @Override
            public void onMessage(ReqT message) {
                if (message instanceof FooRequest) {
                    var foo = ((FooRequest) message).getFoo();
                    headers.put(Metadata.Key.of("x-value"), Metadata.ASCII_STRING_MARSHALLER), foo);
                }
                super.onMessage(message);
            }
        };
    }
}