Skip to content

Commit

Permalink
Merge pull request #943 from sitkoru/grpc/grpc-web
Browse files Browse the repository at this point in the history
Add grpc-web support on server side
  • Loading branch information
SonicGD authored Mar 26, 2024
2 parents 9301468 + 99c6112 commit 0c147e1
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<PackageVersion Include="Grpc.Net.ClientFactory" Version="2.60.0" />
<PackageVersion Include="Grpc.Net.Client.Web" Version="2.60.0" />
<PackageVersion Include="Grpc.AspNetCore" Version="2.60.0" />
<PackageVersion Include="Grpc.AspNetCore.Web" Version="2.60.0" />
<PackageVersion Include="Grpc.AspNetCore.Server.Reflection" Version="2.60.0" />
</ItemGroup>
<!--.NET 8 specific libraries-->
Expand Down
28 changes: 28 additions & 0 deletions src/Sitko.Core.Grpc.Client/GrpcClientModuleOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ internal void ConfigureClient(IServiceCollection services, IHttpClientBuilder bu
configureAuthAction?.Invoke(services, builder);
}

public GrpcClientModuleOptions<TClient> AddMetadataProvider<TMetadataProvider>()
where TMetadataProvider : class, IGrpcMetadataProvider
{
configureAuthAction = (services, builder) =>
{
services.TryAddTransient<IGrpcMetadataProvider, TMetadataProvider>();
builder.AddCallCredentials(async (_, metadata, serviceProvider) =>
{
var provider = serviceProvider.GetRequiredService<IGrpcMetadataProvider>();
var newMetadata = await provider.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);
}
}
});
};
return this;
}

public GrpcClientModuleOptions<TClient> AddTokenAuth<TTokenProvider>()
where TTokenProvider : class, IGrpcTokenProvider
{
Expand Down
6 changes: 6 additions & 0 deletions src/Sitko.Core.Grpc.Client/IGrpcMetadataProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Sitko.Core.Grpc.Client;

public interface IGrpcMetadataProvider
{
Task<Dictionary<string, string>?> GetMetadataAsync();
}
21 changes: 16 additions & 5 deletions src/Sitko.Core.Grpc.Server/BaseGrpcServerModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,21 @@ public abstract class BaseGrpcServerModule<TConfig> : BaseApplicationModule<TCon
{
private readonly List<Action<IEndpointRouteBuilder>> endpointRegistrations = new();

public virtual void RegisterService<TService>(string? requiredAuthorizarionSchemeName) where TService : class =>
public virtual void RegisterService<TService>(string? requiredAuthorizationSchemeName, bool enableGrpcWeb = false)
where TService : class =>
endpointRegistrations.Add(builder =>
{
var grpcBuidler = builder.MapGrpcService<TService>();
if (!string.IsNullOrEmpty(requiredAuthorizarionSchemeName))
var grpcEndpoint = builder.MapGrpcService<TService>();
if (enableGrpcWeb)
{
grpcBuidler.RequireAuthorization(new AuthorizeAttribute
grpcEndpoint = grpcEndpoint.EnableGrpcWeb();
}
if (!string.IsNullOrEmpty(requiredAuthorizationSchemeName))
{
grpcEndpoint.RequireAuthorization(new AuthorizeAttribute
{
AuthenticationSchemes = requiredAuthorizarionSchemeName
AuthenticationSchemes = requiredAuthorizationSchemeName,
});
}
});
Expand Down Expand Up @@ -55,6 +61,11 @@ public void ConfigureEndpoints(IApplicationContext applicationContext,
IApplicationBuilder appBuilder, IEndpointRouteBuilder endpoints)
{
var config = GetOptions(appBuilder.ApplicationServices);
if (config.EnableGrpcWeb)
{
appBuilder.UseGrpcWeb();
}

foreach (var endpointRegistration in endpointRegistrations)
{
endpointRegistration(endpoints);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@ public override async Task ApplicationStarted(IApplicationContext applicationCon
}
}

public override void RegisterService<TService>(string? requiredAuthorizarionSchemeName)
public override void RegisterService<TService>(string? requiredAuthorizationSchemeName, bool enableGrpcWeb = false)
{
base.RegisterService<TService>(requiredAuthorizarionSchemeName);
base.RegisterService<TService>(requiredAuthorizationSchemeName, enableGrpcWeb);
serviceRegistrations.Add(registrar => registrar.RegisterAsync<TService>());
healthChecksRegistrations.Add(healthCheckBuilder =>
healthCheckBuilder.AddCheck<GrpcServiceHealthCheck<TService>>(
$"Grpc service {typeof(TService).BaseType?.DeclaringType?.Name}"));
}
}

14 changes: 11 additions & 3 deletions src/Sitko.Core.Grpc.Server/GrpcServerModuleOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ namespace Sitko.Core.Grpc.Server;
public class GrpcServerModuleOptions : BaseModuleOptions
{
private readonly List<Action<IGrpcServerModule>> serviceRegistrations = new();
internal string? RequiredAuthorizarionSchemeName { get; private set; }
internal string? RequiredAuthorizationSchemeName { get; private set; }
internal bool EnableGrpcWeb { get; private set; }
public string? Host { get; set; }
public int? Port { get; set; }
[JsonIgnore] public Action<IWebHostBuilder>? ConfigureWebHostDefaults { get; set; }
Expand All @@ -29,13 +30,20 @@ public class GrpcServerModuleOptions : BaseModuleOptions

public GrpcServerModuleOptions RegisterService<TService>() where TService : class
{
serviceRegistrations.Add(module => module.RegisterService<TService>(RequiredAuthorizarionSchemeName));
serviceRegistrations.Add(module => module.RegisterService<TService>(RequiredAuthorizationSchemeName));
return this;
}

public GrpcServerModuleOptions RegisterServiceWithGrpcWeb<TService>() where TService : class
{
EnableGrpcWeb = true;
serviceRegistrations.Add(module => module.RegisterService<TService>(RequiredAuthorizationSchemeName, true));
return this;
}

public GrpcServerModuleOptions RequireSchemeAuthorization(string schemeName)
{
RequiredAuthorizarionSchemeName = schemeName;
RequiredAuthorizationSchemeName = schemeName;
return this;
}
}
2 changes: 1 addition & 1 deletion src/Sitko.Core.Grpc.Server/IGrpcServerModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ namespace Sitko.Core.Grpc.Server;

public interface IGrpcServerModule
{
void RegisterService<TService>(string? requiredAuthorizarionSchemeName) where TService : class;
void RegisterService<TService>(string? requiredAuthorizationSchemeName, bool enableGrpcWeb = false) where TService : class;
}

1 change: 1 addition & 0 deletions src/Sitko.Core.Grpc.Server/Sitko.Core.Grpc.Server.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore"/>
<PackageReference Include="Grpc.AspNetCore.Web"/>
<PackageReference Include="Grpc.AspNetCore.Server.Reflection"/>
</ItemGroup>
</Project>

0 comments on commit 0c147e1

Please sign in to comment.