'How can I add Metadata to a GRPC channel using AddGrpcClient in Asp.Net Core?
I’m looking to change the following to use .AddGrpcClient as described here: https://docs.microsoft.com/en-us/aspnet/core/grpc/clientfactory?view=aspnetcore-6.0
The grpc api that I am subscribing to expects metadata with a user name. It works fine when configuring using a Channel and CallInvoker as in my "old code" example. It does not work in my "new code" example.
What am I missing here?
Thanks
old code
public static CallInvoker Configure()
{
var channel = GrpcChannel.ForAddress(_url,
new GrpcChannelOptions
{
Credentials= ChannelCredentials.Insecure,
LoggerFactory = loggerFactory;
});
return channel.Intercept (m => { m.Add("authorization", "fizzbuzz"); return m; });
}
....
var grpcClient = SomeApi.SomeApiClient(Configure());
new code
service.AddGrpcClient<SomeApi.SomeApiClient> (options =>
{
options.Address = new Uri(_url);
})
.ConfigureChannel (options =>
{
options.Credentials = ChannelCredentials.Insecure;
options.LoggerFactory = LoggerFactory.Create(logging => {logging.SetMinimumLevel(LogLevel.Trace)});
})
.AddInterceptor<AuthInterceptor>();
public class AuthInterceptor : Interceptor
{
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse> (
TRequest request,
ClientInterceptor <TRequest, TResponse> context,
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
var m = new MetaData();
m.Add("authorization", "fizzbuzz");
context.Options.WithHeaders(m);
return continuation(request, context);
}
}
Solution 1:[1]
I am not sure what exactly does not work with your code. A difference is, that you do not add new headers but with the new code you exclude all headers and set new ones. This might be due to the metadata (aka headers) are (sometimes) readonly when passed into the interceptor (cf. Metadata.Freeze()).
I would suggest that you should not modify the context but provide a new ClientInterceptorContext with added headers.
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse> (
TRequest request,
ClientInterceptor <TRequest, TResponse> context,
AsyncUnaryCallContinuation<TRequest, TResponse> continuation)
{
var metadata = new MetaData();
metadata.Add("authorization", "fizzbuzz");
var newContext = new ClientInterceptorContext<TRequest, TResponse>(
context.Method,
context.Host,
context.Options.WithHeaders(
(context.Options.Headers ?? new Metadata()).Aggregate(
metadata,
AddIfNonExistent))
);
return continuation(request, newContext);
}
Note, that you do not want to send headers twice, so add the existing headers to the new context:
private static Metadata AddIfNonExistent(Metadata metadata, Metadata.Entry entry)
{
if (metadata.Get(entry.Key) == null) metadata.Add(entry);
return metadata;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Clemens |
