Description
For request metadata, interceptors (both client and server) can simply wrap the context to override the incoming metadata. But there is no such facility for response metadata.
Streaming interceptors can also manage this by wrapping the stream implementation. This allows the interceptor to not only view but also to modify/augment the response metadata.
However, unary interceptors provide no such affordance.
- For the client-side, application code accesses response metadata via completely opaque
CallOption
s, which cannot be intercepted/handled because they are just functions and operate on unexported types. (There may be something clever that could be done with reflection and maybe evenreflect.MakeFunc
, but that's pretty serious gymnastics that would be brittle even if it worked.) - For the server-side, application code sets response metadata using top-level methods that rely on there being a transport tucked inside of a
context.Context
. Since the methods for modifying the context in the correct way are unexported, it is not possible for a server interceptor to wrap the transport, and thus intercept metadata.
A possible solution that would not require any incompatible change to the current API would be to add support for stream interceptors for unary RPCs. This, admittedly, requires a non-trivial fork in logic in the current grpc.processUnaryRPC
and grpc.Invoke
methods (which handle unary RPCs, server- and client-side respectively).
There may be some small optimizations given up to handle unary RPCs through the stream abstractions, but I suspect they would be negligible. New optimizations could potentially be added to grpc.processStreamingRPC
and grpc.NewClientStream
for the unary RPC case. Also, the stream abstraction and how it differs from the underlying transport.Stream
could be revisited to make them more closely aligned, to further reduce overhead.