public static NaosApplicationContextOptions UseOperationsHealth( this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); //naosOptions.Context.Application.UseEndpointRouting(); // needed by middleware to get action/controller https://www.stevejgordon.co.uk/asp-net-core-first-look-at-global-routing-dispatcher //naosOptions.Context.Application.UseEndpoints(endpoints => //{ // endpoints.MapHealthChecks("/health", new HealthCheckOptions // { // ResponseWriter = HealthReportResponseWriter.Write // }); //}); // https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-3.1 naosOptions.Context.Application.UseHealthChecks("/health", new HealthCheckOptions() { Predicate = _ => true, ResponseWriter = HealthReportResponseWriter.Write // or use HealthChecks.UI.Client.UIResponseWriter.WriteHealthCheckUIResponse }); naosOptions.Context.Application.UseHealthChecks("/health/ready", new HealthCheckOptions { Predicate = _ => true, ResponseWriter = HealthReportResponseWriter.Write // or use HealthChecks.UI.Client.UIResponseWriter.WriteHealthCheckUIResponse }); naosOptions.Context.Application.UseHealthChecks("/health/live", new HealthCheckOptions { Predicate = r => r.Tags.Contains("live"), ResponseWriter = HealthReportResponseWriter.Write // or use HealthChecks.UI.Client.UIResponseWriter.WriteHealthCheckUIResponse }); naosOptions.Context.Messages.Add("naos application builder: operations health added"); return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> /// <returns></returns> public static NaosApplicationContextOptions UseNaosExceptionHandling(this NaosApplicationContextOptions naosOptions, ExceptionHandlerMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); naosOptions.Context.Application.UseMiddleware <ExceptionHandlerMiddleware>(Options.Create(options)); naosOptions.Context.Messages.Add($"{LogKeys.Startup} naos application builder: service exceptions added"); return(naosOptions); }
/// <summary> /// Enables poweredby response headers for the API request. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> /// <returns></returns> public static NaosApplicationContextOptions UseNaosServicePoweredBy(this NaosApplicationContextOptions naosOptions, ServicePoweredByMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); naosOptions.Context.Application.UseMiddleware <ServicePoweredByMiddleware>(Options.Create(options)); naosOptions.Context.Messages.Add($"{LogEventKeys.Startup} naos application builder: powered by added"); return(naosOptions); }
/// <summary> /// Enables the service discovery router. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> public static NaosApplicationContextOptions UseNaosServiceDiscoveryRouter( this NaosApplicationContextOptions naosOptions, ServiceDiscoveryRouterMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); #pragma warning disable CS0618 // Type or member is obsolete >> naosOptions.Context.Application.Map("/api/servicediscovery/router/proxy", async proxy => { proxy.UseProxy() } ) naosOptions.Context.Application.RunProxy("/naos/servicediscovery/router/proxy", async context => { var logger = naosOptions.Context.Application.ApplicationServices.GetRequiredService <ILogger>(); var registryClient = naosOptions.Context.Application.ApplicationServices.GetRequiredService <RouterContext>().RegistryClient; // read headers for service/tag var isFoundName = context.Request.Headers.TryGetValue(ServiceDiscoveryRouterHeaders.ServiceName, out var serviceName); var isFoundTag = context.Request.Headers.TryGetValue(ServiceDiscoveryRouterHeaders.ServiceTag, out var serviceTag); if (!isFoundName && !isFoundTag) { context.Response.StatusCode = 400; throw new NaosException($"Router cannot find a service registration based on the provided information (serviceName={serviceName}, serviceTag={serviceTag})"); // = 400 bad request (router headers missing) } var registrations = await registryClient.RegistrationsAsync(serviceName, serviceTag).AnyContext(); var registration = registrations.FirstOrDefault(); // todo: do some kind random/roundrobin if (registration == null) { context.Response.StatusCode = 502; throw new NaosException($"Router cannot find a service registration based on the provided information (serviceName={serviceName}, serviceTag={serviceTag})"); // = 404? 502? https://errorcodespro.com/what-is-http-error-502-bad-gateway/ } // TODO: how is api/registrations NOT forwarded? based on missing router headers? // TODO: round robin https://github.com/damianh/ProxyKit/blob/master/src/Recipes/05_RoundRobin.cs var upstreamHost = new Uri($"{registration.Address}:{registration.Port}"); logger.LogInformation($"{{LogKey:l}} router {{Url}} >> {{Host}} (service={{ServiceName}}, tag={serviceTag})", LogKeys.ServiceDiscovery, context.Request.GetUri(), upstreamHost, registration.Name); return(await context .ForwardTo(upstreamHost) .Log(logger) .CopyXForwardedHeaders() // copies the headers from the incoming requests .AddXForwardedHeaders() // adds the current proxy proto/host/for/pathbase to the X-Forwarded headers .Send().AnyContext()); }); #pragma warning restore CS0618 // Type or member is obsolete naosOptions.Context.Messages.Add("naos application builder: job scheduling added"); // TODO: list available commands/handlers //return app.UseMiddleware<ServiceDiscoveryRouterMiddleware>(Options.Create(options)); return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> public static NaosApplicationContextOptions UseNaosCorrelation(this NaosApplicationContextOptions naosOptions, RequestCorrelationMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); if (naosOptions.Context.Application.ApplicationServices.GetService(typeof(ICorrelationContextFactory)) == null) { throw new InvalidOperationException("Unable to find the required services. You must call the AddRequestCorrelation method in ConfigureServices in the application startup code."); } naosOptions.Context.Application.UseMiddleware <RequestCorrelationMiddleware>(Options.Create(options)); naosOptions.Context.Messages.Add("naos application builder: request correlation added"); return(naosOptions); }
/// <summary> /// Enables service context (descriptor) for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> /// <returns></returns> public static NaosApplicationContextOptions UseNaosServiceContext(this NaosApplicationContextOptions naosOptions, ServiceContextMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); if (naosOptions.Context.Application.ApplicationServices.GetService(typeof(Naos.Core.Common.ServiceDescriptor)) == null) { throw new InvalidOperationException("Unable to find the required services. You must call the AddServiceContext method in ConfigureServices in the application startup code."); } naosOptions.Context.Application.UseMiddleware <ServiceContextMiddleware>(Options.Create(options)); naosOptions.Context.Messages.Add($"{LogEventKeys.Startup} naos application builder: service context added"); return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses /// </summary> /// <param name="naosOptions"></param> /// <param name="requestLoggingMiddlewareOptions"></param> /// <param name="requestStorageMiddlewareOptions"></param> /// <returns></returns> public static NaosApplicationContextOptions UseOperations(this NaosApplicationContextOptions naosOptions, RequestLoggingMiddlewareOptions requestLoggingMiddlewareOptions = null, RequestStorageMiddlewareOptions requestStorageMiddlewareOptions = null) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); naosOptions.Context.Application .UseMiddleware <RequestLoggingMiddleware>( Options.Create(requestLoggingMiddlewareOptions ?? naosOptions.Context.Application.ApplicationServices.GetService <RequestLoggingMiddlewareOptions>() ?? new RequestLoggingMiddlewareOptions())) .UseMiddleware <RequestStorageMiddleware>( Options.Create(requestStorageMiddlewareOptions ?? naosOptions.Context.Application.ApplicationServices.GetService <RequestStorageMiddlewareOptions>() ?? new RequestStorageMiddlewareOptions())); naosOptions.Context.Messages.Add($"{LogEventKeys.Startup} naos application builder: operations added"); var diagnosticListener = naosOptions.Context.Application.ApplicationServices.GetService <DiagnosticListener>(); diagnosticListener?.SubscribeWithAdapter(new NaosDiagnosticListener(naosOptions.Context.Application.ApplicationServices.GetService <ILoggerFactory>())); return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="options"></param> public static NaosApplicationContextOptions UseAuthenticationChallenge(this NaosApplicationContextOptions naosOptions, OidcAuthenticationChallengeMiddlewareOptions options) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); EnsureArg.IsNotNull(options, nameof(options)); var provider = naosOptions.Context.Application.ApplicationServices.GetService <IAuthenticationSchemeProvider>(); if (provider != null) { if (provider.GetDefaultChallengeSchemeAsync().Result?.Name == Authentication.OpenIdConnect.OpenIdConnectDefaults.AuthenticationScheme) { naosOptions.Context.Application.UseMiddleware <OidcAuthenticationChallengeMiddleware>(Options.Create(options)); naosOptions.Context.Messages.Add("naos application builder: authentication challenge"); } // TODO: register other middleware for different authentication schemes (easyauth?) } return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> public static NaosApplicationContextOptions UseCommandEndpoints(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); var routeMatcher = new RouteMatcher(); foreach (var registration in naosOptions.Context.Application.ApplicationServices.GetServices <CommandRequestRegistration>().Safe() .Where(r => !r.Route.IsNullOrEmpty())) { naosOptions.Context.Application.UseMiddleware <CommandRequestMiddleware>( Options.Create(new CommandRequestMiddlewareOptions { Registration = registration, RouteMatcher = routeMatcher })); naosOptions.Context.Messages.Add($"naos application builder: command requests added (route={registration.Route}, method={registration.RequestMethod}, type={registration.CommandType.PrettyName()})"); } return(naosOptions); }
/// <summary> /// Enables tracing for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="requestTracingMiddlewareOptions"></param> public static NaosApplicationContextOptions UseOperationsTracing( this NaosApplicationContextOptions naosOptions, RequestTracingMiddlewareOptions requestTracingMiddlewareOptions = null) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); using (var scope = naosOptions.Context.Application.ApplicationServices.CreateScope()) { if (scope.ServiceProvider.GetService(typeof(ITracer)) == null) // resolve scoped service { throw new InvalidOperationException("Unable to find the required services. You must call the AddTracing method in ConfigureServices in the application startup code."); } } //naosOptions.Context.Application.UseEndpointRouting(); // needed by middleware to get action/controller https://www.stevejgordon.co.uk/asp-net-core-first-look-at-global-routing-dispatcher naosOptions.Context.Application.UseMiddleware <RequestTracingMiddleware>( Options.Create(requestTracingMiddlewareOptions ?? naosOptions.Context.Application.ApplicationServices.GetService <RequestTracingMiddlewareOptions>() ?? new RequestTracingMiddlewareOptions())); naosOptions.Context.Messages.Add("naos application builder: operations request tracing added"); return(naosOptions); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> /// <param name="requestLoggingMiddlewareOptions"></param> /// <param name="requestStorageMiddlewareOptions"></param> public static NaosApplicationContextOptions UseOperationsLogging( this NaosApplicationContextOptions naosOptions, RequestLoggingMiddlewareOptions requestLoggingMiddlewareOptions = null, RequestStorageMiddlewareOptions requestStorageMiddlewareOptions = null) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); //naosOptions.Context.Application.UseEndpointRouting(); // needed by middleware to get action/controller https://www.stevejgordon.co.uk/asp-net-core-first-look-at-global-routing-dispatcher naosOptions.Context.Application .UseMiddleware <RequestLoggingMiddleware>( Options.Create(requestLoggingMiddlewareOptions ?? naosOptions.Context.Application.ApplicationServices.GetService <RequestLoggingMiddlewareOptions>() ?? new RequestLoggingMiddlewareOptions())) .UseMiddleware <RequestStorageMiddleware>( Options.Create(requestStorageMiddlewareOptions ?? naosOptions.Context.Application.ApplicationServices.GetService <RequestStorageMiddlewareOptions>() ?? new RequestStorageMiddlewareOptions())); naosOptions.Context.Messages.Add("naos application builder: operations request logging added"); var diagnosticListener = naosOptions.Context.Application.ApplicationServices.GetService <DiagnosticListener>(); diagnosticListener?.SubscribeWithAdapter(new NaosDiagnosticListener(naosOptions.Context.Application.ApplicationServices.GetService <ILoggerFactory>())); return(naosOptions); }
/// <summary> /// Force authentication for all endpoints (mvc + custom middleware) /// </summary> /// <param name="naosOptions"></param> public static NaosApplicationContextOptions UseAuthenticationChallenge(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); return(naosOptions.UseAuthenticationChallenge(new OidcAuthenticationChallengeMiddlewareOptions())); }
/// <summary> /// Enables correlation/request ids for the API request/responses. /// </summary> /// <param name="naosOptions"></param> public static NaosApplicationContextOptions UseRequestCorrelation(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); return(naosOptions.UseNaosCorrelation(new RequestCorrelationMiddlewareOptions())); }
public static NaosApplicationContextOptions UseServiceExceptions(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); return(naosOptions.UseNaosExceptionHandling(new ExceptionHandlerMiddlewareOptions())); }
/// <summary> /// Enables the service discovery router /// </summary> /// <param name="naosOptions"></param> /// <returns></returns> public static NaosApplicationContextOptions UseServiceDiscoveryRouter(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); return(naosOptions.UseNaosServiceDiscoveryRouter(new ServiceDiscoveryRouterMiddlewareOptions())); }
/// <summary> /// Enables poweredby response headers for the API request. /// </summary> /// <param name="naosOptions"></param> /// <returns></returns> public static NaosApplicationContextOptions UseServicePoweredBy(this NaosApplicationContextOptions naosOptions) { EnsureArg.IsNotNull(naosOptions, nameof(naosOptions)); return(naosOptions.UseNaosServicePoweredBy(new ServicePoweredByMiddlewareOptions())); }