Created
June 30, 2020 14:49
-
-
Save schmitch/585fe6cd4e61151c3b9224435210bb8d to your computer and use it in GitHub Desktop.
standalone grpc server builder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.AspNetCore.Builder; | |
using Microsoft.AspNetCore.Hosting.Builder; | |
using Microsoft.AspNetCore.Hosting.Server; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Http.Features; | |
using Microsoft.AspNetCore.Routing; | |
using Microsoft.AspNetCore.Server.Kestrel.Core; | |
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Hosting; | |
using Microsoft.Extensions.Logging; | |
using Microsoft.Extensions.Options; | |
namespace WorkerWebProject | |
{ | |
public class GrpcServerBuilder | |
{ | |
private readonly KestrelServerOptions _kestrelServerOptions; | |
private readonly SocketTransportOptions _socketTransportOptions = new SocketTransportOptions(); | |
private Action<IApplicationBuilder> _pipelineAction = null; | |
private readonly List<Action<IEndpointRouteBuilder>> _routes = new List<Action<IEndpointRouteBuilder>>(); | |
private GrpcServerBuilder(KestrelServerOptions kestrelServerOptions) | |
{ | |
_kestrelServerOptions = kestrelServerOptions; | |
} | |
public static GrpcServerBuilder Create(int port, Action<ListenOptions> listenOptions = null) | |
{ | |
var options = new KestrelServerOptions(); | |
options.ListenLocalhost(port, listenOptions ?? (o => o.Protocols = HttpProtocols.Http2)); | |
return new GrpcServerBuilder(options); | |
} | |
public GrpcServerBuilder ConfigureKestrel(Action<KestrelServerOptions> options) | |
{ | |
options(_kestrelServerOptions); | |
return this; | |
} | |
public GrpcServerBuilder ConfigureSocketTransport(Action<SocketTransportOptions> options) | |
{ | |
options(_socketTransportOptions); | |
return this; | |
} | |
public GrpcServerBuilder AddPipeline(Action<IApplicationBuilder> app) | |
{ | |
_pipelineAction = app; | |
return this; | |
} | |
public GrpcServerBuilder AddService<T>() where T : class | |
{ | |
_routes.Add(e => e.MapGrpcService<T>()); | |
return this; | |
} | |
public GrpcWorker Build(IServiceProvider provider) | |
{ | |
return new GrpcWorker(_kestrelServerOptions, provider, _socketTransportOptions, _routes, _pipelineAction); | |
} | |
private class GrpcApplication : IHttpApplication<HttpContext> | |
{ | |
private readonly RequestDelegate _request; | |
private readonly IHttpContextFactory _httpContextFactory; | |
public GrpcApplication(RequestDelegate request, IServiceProvider provider) | |
{ | |
_request = request; | |
_httpContextFactory = new DefaultHttpContextFactory(provider); | |
} | |
public HttpContext CreateContext(IFeatureCollection contextFeatures) | |
{ | |
return _httpContextFactory.Create(contextFeatures); | |
} | |
public void DisposeContext(HttpContext context, Exception exception) | |
{ | |
_httpContextFactory.Dispose(context); | |
} | |
public async Task ProcessRequestAsync(HttpContext context) | |
{ | |
await _request(context); | |
} | |
} | |
public class GrpcWorker : IHostedService | |
{ | |
private KestrelServer _server; | |
private readonly KestrelServerOptions _kestrelServerOptions; | |
private readonly IServiceProvider _provider; | |
private readonly SocketTransportOptions _socketTransportOptions; | |
private readonly List<Action<IEndpointRouteBuilder>> _routes; | |
private readonly Action<IApplicationBuilder> _pipelineAction; | |
internal GrpcWorker( | |
KestrelServerOptions kestrelServerOptions, | |
IServiceProvider provider, | |
SocketTransportOptions socketTransportOptions, | |
List<Action<IEndpointRouteBuilder>> routes, | |
Action<IApplicationBuilder> pipelineAction) | |
{ | |
_kestrelServerOptions = kestrelServerOptions; | |
_provider = provider; | |
_socketTransportOptions = socketTransportOptions; | |
_routes = routes; | |
_pipelineAction = pipelineAction; | |
} | |
public async Task StartAsync(CancellationToken cancellationToken) | |
{ | |
var loggerFactory = _provider.GetRequiredService<ILoggerFactory>(); | |
var socketTransportFactory = new SocketTransportFactory( | |
Options.Create(_socketTransportOptions), | |
loggerFactory); | |
_server = new KestrelServer( | |
Options.Create(_kestrelServerOptions), | |
socketTransportFactory, | |
loggerFactory); | |
var builder = new ApplicationBuilderFactory(_provider).CreateBuilder(_server.Features); | |
_pipelineAction?.Invoke(builder); | |
builder.UseRouting(); | |
builder.UseEndpoints(e => | |
{ | |
foreach (var action in _routes) | |
{ | |
action(e); | |
} | |
}); | |
var requestDelegate = builder.Build(); | |
await _server.StartAsync(new GrpcApplication(requestDelegate, _provider), cancellationToken); | |
} | |
public async Task StopAsync(CancellationToken cancellationToken) | |
{ | |
await _server.StopAsync(cancellationToken); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment