Skip to content

Commit

Permalink
Merge pull request #947 from sitkoru/grpc/client/multiple-metadata-pr…
Browse files Browse the repository at this point in the history
…oviders

Allow multiple metadata providers
  • Loading branch information
pogromistik authored Apr 16, 2024
2 parents 799213c + ce0a309 commit f2329ac
Showing 1 changed file with 46 additions and 38 deletions.
84 changes: 46 additions & 38 deletions src/Sitko.Core.Grpc.Client/GrpcClientModuleOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ namespace Sitko.Core.Grpc.Client;
[PublicAPI]
public class GrpcClientModuleOptions<TClient> : BaseModuleOptions where TClient : ClientBase<TClient>
{
private const string AuthorizationHeader = "Authorization";
private readonly Dictionary<Type, Action<IServiceCollection, IHttpClientBuilder>> interceptorActions = new();
private Action<IServiceCollection, IHttpClientBuilder>? configureAuthAction;
private readonly List<Action<IServiceCollection>> configureServicesActions = new();
public bool EnableHttp2UnencryptedSupport { get; set; }
public bool DisableCertificatesValidation { get; set; }
[JsonIgnore] public Action<GrpcChannelOptions>? ConfigureChannelOptions { get; set; }
Expand All @@ -26,60 +27,67 @@ internal void ConfigureClient(IServiceCollection services, IHttpClientBuilder bu
configure(services, builder);
}

configureAuthAction?.Invoke(services, builder);
}

public GrpcClientModuleOptions<TClient> AddMetadataProvider<TMetadataProvider>()
where TMetadataProvider : class, IGrpcMetadataProvider
{
configureAuthAction = (services, builder) =>
foreach (var configure in configureServicesActions)
{
services.TryAddTransient<IGrpcMetadataProvider, TMetadataProvider>();
builder.AddCallCredentials(async (_, metadata, serviceProvider) =>
configure(services);
}

builder.AddCallCredentials(async (_, metadata, serviceProvider) =>
{
var tokenProvider = serviceProvider.GetService<IGrpcTokenProvider>();
if (tokenProvider is not null)
{
var provider = serviceProvider.GetRequiredService<IGrpcMetadataProvider>();
var newMetadata = await provider.GetMetadataAsync();
var token = await tokenProvider.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
{
SetMetadata(metadata, AuthorizationHeader, token);
}
}

var metadataProviders = serviceProvider.GetServices<IGrpcMetadataProvider>();
foreach (var metadataProvider in metadataProviders)
{
var newMetadata = await metadataProvider.GetMetadataAsync();
if (newMetadata?.Count > 0)
{
foreach (var (key, value) in newMetadata)
{
var oldEntries = metadata.GetAll(key);
foreach (var entry in oldEntries)
{
metadata.Remove(entry);
}

metadata.Add(key, value);
SetMetadata(metadata, key, value);
}
}
});
};
}
});
}

private static void SetMetadata(Metadata metadata, string key, string value)
{
var oldEntries = metadata.GetAll(key);
foreach (var entry in oldEntries)
{
metadata.Remove(entry);
}

metadata.Add(key, value);
}

public GrpcClientModuleOptions<TClient> AddMetadataProvider<TMetadataProvider>()
where TMetadataProvider : class, IGrpcMetadataProvider
{
configureServicesActions.Add(services =>
{
services.AddTransient<IGrpcMetadataProvider, TMetadataProvider>();
});
return this;
}

public GrpcClientModuleOptions<TClient> AddTokenAuth<TTokenProvider>()
where TTokenProvider : class, IGrpcTokenProvider
{
const string AuthorizationHeader = "Authorization";
configureAuthAction = (services, builder) =>
configureServicesActions.Add(services =>
{
services.TryAddTransient<IGrpcTokenProvider, TTokenProvider>();
builder.AddCallCredentials(async (_, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<IGrpcTokenProvider>();
var token = await provider.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
{
var oldAuthHeaders = metadata.GetAll(AuthorizationHeader);
foreach (var entry in oldAuthHeaders)
{
metadata.Remove(entry);
}

metadata.Add(AuthorizationHeader, token);
}
});
};
});
return this;
}

Expand Down

0 comments on commit f2329ac

Please sign in to comment.