Yes you need to implement interceptors to get access custom headers.
The generated server interface always uses the default Protobuf Marshaller which will always deserialize.
If you want to avoid deserialization, you can't use the generated server interface.
Here is a recipe that may work for you:
2. Custom
MethodDescriptor<InputStream, InputStream> that use the Marshaller above. Let's say they are MD1, MD2, ...
3. Define a
Context.Key<Boolean>, say PASS_THROUGH. In your server interceptor, if you find your custom header says pass-through, set this context value in the context before calling next.newCall(). This is necessary because the service impl only has access to the Context, but not headers.
4. Write the service impl in the following pattern:
class FooImpl implements BindableService {
@Override
public ServerServiceDefinition bindService() {
return ServerServiceDefinition.builder("FooService")
.addMethod(MD1,
ServerCalls.asyncUnaryCall( // suppose MD1 is unary
new ServerCalls.UnaryMethod<InputStream, InputStream>() {
@Override
public void invoke(
InputStream request, StreamObserver<InputStream> responseObserver) {
if (PASS_THROUGH.get() != null) {
// send request out
// You won't be able to use the generated stub here.
// Instead, you will need call newCall() on an out-going Channel with MD1.
} else {
// parse request and handle it locally
}
}
}))
.addMethod(MD2,
....
)
...
.build();
}
}
5.
Register this server impl (add the interceptor too) to the gRPC Server builder.