c# gRPC interceptor for server outgoing messages

407 views
Skip to first unread message

Razvan Simerea

unread,
Oct 5, 2023, 3:10:37 AM10/5/23
to grpc.io
In the Microsoft docs on gRPC interceptors for .NET it is said that: 
"gRPC server interceptors intercept incoming RPC requests. They provide access to the incoming request, the outgoing response, and the context for a server-side call."

However, in the implementation, I couldn't find a method in the base interceptor for managing outgoing messages, but only incoming.

Has anyone ever implemented an outgoing message server interceptor for .NET?


Christopher Warrington - MSFT

unread,
Oct 5, 2023, 9:38:23 PM10/5/23
to grpc.io
For unary and client streaming calls, you can access to the response message
by looking at the return of the continuation before you return from your
interceptor.

Here's a slight modification of the example UnaryServerHandler method in
ServerLoggerInterceptor.cs [0] that highlights where you can look at the
response message:

    public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
        TRequest request,
        ServerCallContext context,
        UnaryServerMethod<TRequest, TResponse> continuation)
    {
        LogCall<TRequest, TResponse>(MethodType.Unary, context);

        try
        {
            TResponse response = await continuation(request, context);
            // you have access to the response message here
            return response;
        }
        catch (Exception ex)
        {
            // Note: The gRPC framework also logs exceptions thrown by handlers to .NET Core logging.
            _logger.LogError(ex, $"Error thrown by {context.Method}.");


            throw;
        }
    }

For server streaming and duplex calls, your interceptor can pass its own
implementation of IServerStreamWriter to the continuation. Then, it will be
able to see the calls to WriteAsync to be able to inspect the messages. It
will also have to forward those on to the original IServerStreamWriter
implementation. For example (warning: email code, not tested):

public class ObservingServerStreamWriter<TResponse> : IServerStreamWriter<TResponse>
{
    private readonly IServerStreamWriter<TResponse> _inner;

    public ObservingServerStreamWriter(IServerStreamingWriter<IServerStreamWriter> inner)
    {
        _inner = inner;
        // capture whatever other state you need here
    }

    public WriteOptions? WriteOptions
    {
        get { return _inner.WriteOptions }
        set { _inner.WriteOptions = value; }
    }

    public Task WriteAsync<TResponse>(T message)
    {
        // you can observe message here
        return _inner.WriteAsync(message);
    }
}

--
Christopher Warrington
Microsoft Corp, but not on the gRPC team

[0]: https://github.com/grpc/grpc-dotnet/blob/207e8066f3ed2f6c656e565c07c746e282f54ff4/examples/Interceptor/Server/ServerLoggerInterceptor.cs#L33-L51
Reply all
Reply to author
Forward
0 new messages