Пример #1
0
        public static IDrexBuilder AddMongo(this IDrexBuilder builder, MongoDbOptions mongoOptions)
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddSingleton(mongoOptions);
            builder.Services.AddSingleton <IMongoClient>(sp =>
            {
                var options = sp.GetService <MongoDbOptions>();
                return(new MongoClient(options.ConnectionString));
            });
            builder.Services.AddTransient(sp =>
            {
                var options = sp.GetService <MongoDbOptions>();
                var client  = sp.GetService <IMongoClient>();
                return(client.GetDatabase(options.Database));
            });
            builder.Services.AddTransient <IMongoDbInitializer, MongoDbInitializer>();
            builder.Services.AddTransient <IMongoSessionFactory, MongoSessionFactory>();

            builder.AddInitializer <IMongoDbInitializer>();

            return(builder);
        }
Пример #2
0
        public static IDrexBuilder AddSwaggerDocs(this IDrexBuilder builder, SwaggerOptions options)
        {
            if (!options.Enabled || !builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddSingleton(options);
            builder.Services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(options.Name, new OpenApiInfo {
                    Title = options.Title, Version = options.Version
                });
                if (options.IncludeSecurity)
                {
                    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                    {
                        Description =
                            "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                        Name = "Authorization",
                        In   = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey
                    });
                }
            });

            return(builder);
        }
Пример #3
0
        public static IDrexBuilder AddConsul(this IDrexBuilder builder, ConsulOptions options,
                                             HttpClientOptions httpClientOptions)
        {
            builder.Services.AddSingleton(options);
            if (!options.Enabled || !builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (httpClientOptions.Type?.ToLowerInvariant() == "consul")
            {
                builder.Services.AddTransient <ConsulServiceDiscoveryMessageHandler>();
                builder.Services.AddHttpClient <IConsulHttpClient, ConsulHttpClient>("consul-http")
                .AddHttpMessageHandler <ConsulServiceDiscoveryMessageHandler>();
                builder.RemoveHttpClient();
                builder.Services.AddHttpClient <IHttpClient, ConsulHttpClient>("consul")
                .AddHttpMessageHandler <ConsulServiceDiscoveryMessageHandler>();
            }

            builder.Services.AddTransient <IConsulServicesRegistry, ConsulServicesRegistry>();
            var registration = builder.CreateConsulAgentRegistration(options);

            if (registration is null)
            {
                return(builder);
            }

            builder.Services.AddSingleton(registration);

            return(builder);
        }
Пример #4
0
        private static IDrexBuilder AddServiceClient <T>(this IDrexBuilder builder, string serviceName,
                                                         RestEaseOptions options, Action <IDrexBuilder> registerFabio)
            where T : class
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            var clientName = typeof(T).ToString();

            switch (options.LoadBalancer?.ToLowerInvariant())
            {
            case "consul":
                builder.AddConsulHttpClient(clientName, serviceName);
                break;

            case "fabio":
                builder.AddFabioHttpClient(clientName, serviceName);
                break;

            default:
                ConfigureDefaultClient(builder.Services, clientName, serviceName, options);
                break;
            }

            ConfigureForwarder <T>(builder.Services, clientName);

            registerFabio(builder);

            return(builder);
        }
Пример #5
0
        public static IDrexBuilder AddRabbitMq(this IDrexBuilder builder, string sectionName = SectionName,
                                               Func <IRabbitMqPluginsRegistry, IRabbitMqPluginsRegistry> plugins = null)
        {
            if (string.IsNullOrWhiteSpace(sectionName))
            {
                sectionName = SectionName;
            }

            var options = builder.GetOptions <RabbitMqOptions>(sectionName);

            builder.Services.AddSingleton(options);
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (options.HostNames is null || !options.HostNames.Any())
            {
                throw new ArgumentException("RabbitMQ hostnames are not specified.", nameof(options.HostNames));
            }

            builder.Services.AddSingleton <IContextProvider, ContextProvider>();
            builder.Services.AddSingleton <ICorrelationContextAccessor>(new CorrelationContextAccessor());
            builder.Services.AddSingleton <IMessagePropertiesAccessor>(new MessagePropertiesAccessor());
            builder.Services.AddSingleton <IConventionsBuilder, ConventionsBuilder>();
            builder.Services.AddSingleton <IConventionsProvider, ConventionsProvider>();
            builder.Services.AddSingleton <IConventionsRegistry, ConventionsRegistry>();
            builder.Services.AddSingleton <IRabbitMqSerializer, NewtonsoftJsonRabbitMqSerializer>();
            builder.Services.AddSingleton <IRabbitMqClient, RabbitMqClient>();
            builder.Services.AddSingleton <IBusPublisher, RabbitMqPublisher>();
            builder.Services.AddSingleton <IBusSubscriber, RabbitMqSubscriber>();
            builder.Services.AddTransient <RabbitMqExchangeInitializer>();
            builder.Services.AddHostedService <RabbitMqHostedService>();
            builder.AddInitializer <RabbitMqExchangeInitializer>();

            var pluginsRegistry = new RabbitMqPluginsRegistry();

            builder.Services.AddSingleton <IRabbitMqPluginsRegistryAccessor>(pluginsRegistry);
            builder.Services.AddSingleton <IRabbitMqPluginsExecutor, RabbitMqPluginsExecutor>();
            plugins?.Invoke(pluginsRegistry);

            var connection = new ConnectionFactory
            {
                Port        = options.Port,
                VirtualHost = options.VirtualHost,
                UserName    = options.Username,
                Password    = options.Password,
                RequestedConnectionTimeout = options.RequestedConnectionTimeout,
                SocketReadTimeout          = options.SocketReadTimeout,
                SocketWriteTimeout         = options.SocketWriteTimeout,
                RequestedChannelMax        = options.RequestedChannelMax,
                RequestedFrameMax          = options.RequestedFrameMax,
                RequestedHeartbeat         = options.RequestedHeartbeat,
                UseBackgroundThreadsForIO  = options.UseBackgroundThreadsForIO,
                DispatchConsumersAsync     = true,
                Ssl = options.Ssl is null
                    ? new SslOption()
                    : new SslOption(options.Ssl.ServerName, options.Ssl.CertificatePath, options.Ssl.Enabled)
            }.CreateConnection(options.HostNames.ToList(), options.ConnectionName);
Пример #6
0
        public static IDrexBuilder AddDistributedAccessTokenValidator(this IDrexBuilder builder)
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddSingleton <IAccessTokenService, DistributedAccessTokenService>();

            return(builder);
        }
Пример #7
0
        public static IDrexBuilder AddRedis(this IDrexBuilder builder, RedisOptions options)
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddStackExchangeRedisCache(o =>
            {
                o.Configuration = options.ConnectionString;
                o.InstanceName  = options.Instance;
            });

            return(builder);
        }
Пример #8
0
        public static IDrexBuilder AddCertificateAuthentication(this IDrexBuilder builder,
                                                                string sectionName = SectionName, Type permissionValidatorType = null)
        {
            var options = builder.GetOptions <SecurityOptions>(sectionName);

            builder.Services.AddSingleton(options);
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (options.Certificate is null || !options.Certificate.Enabled)
            {
                return(builder);
            }

            if (permissionValidatorType is {})
Пример #9
0
        public static IDrexBuilder AddSqlServer <TMyDbContext>(this IDrexBuilder builder,
                                                               SqlServerOptions sqlServerOptions)
            where TMyDbContext : DbContext
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddSingleton(sqlServerOptions);

            builder.Services.AddTransient <ISqlServerInitializer, SqlServerInitializer>();

            builder.AddInitializer <ISqlServerInitializer>();
            builder.Services.AddEntityFrameworkMsSql <TMyDbContext>(sqlServerOptions);

            return(builder);
        }
Пример #10
0
        public static IDrexBuilder AddHttpClient(this IDrexBuilder builder,
                                                 string clientName = "Drex",
                                                 IEnumerable <string> maskedRequestUrlParts = null, string sectionName = SectionName)
        {
            if (string.IsNullOrWhiteSpace(sectionName))
            {
                sectionName = SectionName;
            }

            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (string.IsNullOrWhiteSpace(clientName))
            {
                throw new ArgumentException("HTTP client name cannot be empty.", nameof(clientName));
            }

            var options = builder.GetOptions <HttpClientOptions>(sectionName);

            if (maskedRequestUrlParts is {} && options.RequestMasking is {})
Пример #11
0
        private static IDrexBuilder AddFabio(this IDrexBuilder builder, FabioOptions fabioOptions,
                                             HttpClientOptions httpClientOptions, Action <IDrexBuilder> registerConsul)
        {
            registerConsul(builder);
            builder.Services.AddSingleton(fabioOptions);

            if (!fabioOptions.Enabled || !builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (httpClientOptions.Type?.ToLowerInvariant() == "fabio")
            {
                builder.Services.AddTransient <FabioMessageHandler>();
                builder.Services.AddHttpClient <IFabioHttpClient, FabioHttpClient>("fabio-http")
                .AddHttpMessageHandler <FabioMessageHandler>();
                builder.RemoveHttpClient();
                builder.Services.AddHttpClient <IHttpClient, FabioHttpClient>("fabio")
                .AddHttpMessageHandler <FabioMessageHandler>();
            }

            using (var serviceProvider = builder.Services.BuildServiceProvider())
            {
                var registration = serviceProvider.GetService <ServiceRegistration>();
                var tags         = GetFabioTags(registration.Name, fabioOptions.Service);
                if (registration.Tags is null)
                {
                    registration.Tags = tags;
                }
                else
                {
                    registration.Tags.AddRange(tags);
                }

                builder.Services.UpdateConsulRegistration(registration);
            }

            return(builder);
        }
Пример #12
0
        private static IDrexBuilder AddJwt(this IDrexBuilder builder, JwtOptions options,
                                           Action <JwtBearerOptions> optionsFactory = null)
        {
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddSingleton <IJwtHandler, JwtHandler>();
            builder.Services.AddSingleton <IAccessTokenService, InMemoryAccessTokenService>();
            builder.Services.AddTransient <AccessTokenValidatorMiddleware>();

            var tokenValidationParameters = new TokenValidationParameters
            {
                RequireAudience          = options.RequireAudience,
                ValidIssuer              = options.ValidIssuer,
                ValidIssuers             = options.ValidIssuers,
                ValidateActor            = options.ValidateActor,
                ValidAudience            = options.ValidAudience,
                ValidAudiences           = options.ValidAudiences,
                ValidateAudience         = options.ValidateAudience,
                ValidateIssuer           = options.ValidateIssuer,
                ValidateLifetime         = options.ValidateLifetime,
                ValidateTokenReplay      = options.ValidateTokenReplay,
                ValidateIssuerSigningKey = options.ValidateIssuerSigningKey,
                SaveSigninToken          = options.SaveSigninToken,
                RequireExpirationTime    = options.RequireExpirationTime,
                RequireSignedTokens      = options.RequireSignedTokens,
                ClockSkew = TimeSpan.Zero
            };

            if (!string.IsNullOrWhiteSpace(options.AuthenticationType))
            {
                tokenValidationParameters.AuthenticationType = options.AuthenticationType;
            }

            var hasCertificate = false;

            if (options.Certificate is {})
Пример #13
0
        private static IDrexBuilder AddRabbitMq <TContext>(this IDrexBuilder builder,
                                                           RabbitMqOptions options,
                                                           Func <IRabbitMqPluginRegister, IRabbitMqPluginRegister> plugins, Action <IDrexBuilder> registerRedis)
            where TContext : class, new()
        {
            builder.Services.AddSingleton(options);
            builder.Services.AddSingleton <RawRabbitConfiguration>(options);
            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            builder.Services.AddTransient <IBusPublisher, BusPublisher>();
            if (options.MessageProcessor?.Enabled == true)
            {
                switch (options.MessageProcessor.Type?.ToLowerInvariant())
                {
                case "redis":
                    registerRedis(builder);
                    builder.Services.AddTransient <IMessageProcessor, RedisMessageProcessor>();
                    break;

                default:
                    builder.Services.AddTransient <IMessageProcessor, InMemoryMessageProcessor>();
                    break;
                }
            }
            else
            {
                builder.Services.AddSingleton <IMessageProcessor, EmptyMessageProcessor>();
            }

            builder.Services.AddSingleton <ICorrelationContextAccessor>(new CorrelationContextAccessor());

            ConfigureBus <TContext>(builder, plugins);

            return(builder);
        }
Пример #14
0
        public static IDrexBuilder AddWebApi(this IDrexBuilder builder,
                                             Action <IMvcCoreBuilder> configureMvc = null,
                                             IJsonSerializer jsonSerializer        = null, string sectionName = SectionName)
        {
            if (string.IsNullOrWhiteSpace(sectionName))
            {
                sectionName = SectionName;
            }

            if (!builder.TryRegister(RegistryName))
            {
                return(builder);
            }

            if (jsonSerializer is null)
            {
                var factory = new JsonSerializerFactory(new JsonSerializerSettings
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver(),
                    Converters       = { new StringEnumConverter(true) }
                });
                jsonSerializer = factory.GetSerializer();
            }

            if (jsonSerializer.GetType().Namespace?.Contains("Newtonsoft") == true)
            {
                builder.Services.Configure <KestrelServerOptions>(o => o.AllowSynchronousIO = true);
                builder.Services.Configure <IISServerOptions>(o => o.AllowSynchronousIO     = true);
            }

            builder.Services.AddSingleton(jsonSerializer);
            builder.Services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();
            builder.Services.AddSingleton(new WebApiEndpointDefinitions());
            var options = builder.GetOptions <WebApiOptions>(sectionName);

            builder.Services.AddSingleton(options);
            _bindRequestFromRoute = options.BindRequestFromRoute;

            var mvcCoreBuilder = builder.Services
                                 .AddLogging()
                                 .AddMvcCore();

            mvcCoreBuilder.AddMvcOptions(o =>
            {
                o.OutputFormatters.Clear();
                o.OutputFormatters.Add(new JsonOutputFormatter(jsonSerializer));
                o.InputFormatters.Clear();
                o.InputFormatters.Add(new JsonInputFormatter(jsonSerializer));
            })
            .AddDataAnnotations()
            .AddApiExplorer()
            .AddAuthorization();

            configureMvc?.Invoke(mvcCoreBuilder);

            // This method gets called by the runtime. Use this method to add services to the container.
            builder.Services.Scan(s =>
                                  s.FromAssemblies(AppDomain.CurrentDomain.GetAssemblies())
                                  .AddClasses(c => c.AssignableTo(typeof(IRequestHandler <,>)))
                                  .AsImplementedInterfaces()
                                  .WithTransientLifetime());

            builder.Services.AddTransient <IRequestDispatcher, RequestDispatcher>();

            return(builder);
        }
Пример #15
0
        public static IDrexBuilder AddMetrics(this IDrexBuilder builder, MetricsOptions metricsOptions,
                                              AppOptions appOptions)
        {
            builder.Services.AddSingleton(metricsOptions);
            if (!builder.TryRegister(RegistryName) || !metricsOptions.Enabled || _initialized)
            {
                return(builder);
            }

            _initialized = true;

            //TODO: Remove once fixed https://github.com/AppMetrics/AppMetrics/issues/396
            builder.Services.Configure <KestrelServerOptions>(o => o.AllowSynchronousIO = true);
            builder.Services.Configure <IISServerOptions>(o => o.AllowSynchronousIO     = true);

            var metricsBuilder = new MetricsBuilder().Configuration.Configure(cfg =>
            {
                var tags = metricsOptions.Tags;
                if (tags is null)
                {
                    return;
                }

                tags.TryGetValue("app", out var app);
                tags.TryGetValue("env", out var env);
                tags.TryGetValue("server", out var server);
                cfg.AddAppTag(string.IsNullOrWhiteSpace(app) ? appOptions.Service : app);
                cfg.AddEnvTag(string.IsNullOrWhiteSpace(env) ? null : env);
                cfg.AddServerTag(string.IsNullOrWhiteSpace(server) ? null : server);
                if (!string.IsNullOrWhiteSpace(appOptions.Instance))
                {
                    cfg.GlobalTags.Add("instance", appOptions.Instance);
                }

                if (!string.IsNullOrWhiteSpace(appOptions.Version))
                {
                    cfg.GlobalTags.Add("version", appOptions.Version);
                }

                foreach (var tag in tags)
                {
                    if (cfg.GlobalTags.ContainsKey(tag.Key))
                    {
                        cfg.GlobalTags.Remove(tag.Key);
                    }

                    if (!cfg.GlobalTags.ContainsKey(tag.Key))
                    {
                        cfg.GlobalTags.TryAdd(tag.Key, tag.Value);
                    }
                }
            });

            if (metricsOptions.InfluxEnabled)
            {
                metricsBuilder.Report.ToInfluxDb(o =>
                {
                    o.InfluxDb.Database = metricsOptions.Database;
                    o.InfluxDb.BaseUri  = new Uri(metricsOptions.InfluxUrl);
                    o.InfluxDb.CreateDataBaseIfNotExists = true;
                    o.FlushInterval = TimeSpan.FromSeconds(metricsOptions.Interval);
                });
            }

            var metrics = metricsBuilder.Build();
            var metricsWebHostOptions = GetMetricsWebHostOptions(metricsOptions);

            using (var serviceProvider = builder.Services.BuildServiceProvider())
            {
                var configuration = serviceProvider.GetService <IConfiguration>();
                builder.Services.AddHealth();
                builder.Services.AddHealthEndpoints(configuration);
                builder.Services.AddMetricsTrackingMiddleware(configuration);
                builder.Services.AddMetricsEndpoints(configuration);
                builder.Services.AddSingleton <IStartupFilter>(new DefaultMetricsEndpointsStartupFilter());
                builder.Services.AddSingleton <IStartupFilter>(new DefaultHealthEndpointsStartupFilter());
                builder.Services.AddSingleton <IStartupFilter>(new DefaultMetricsTrackingStartupFilter());
                builder.Services.AddMetricsReportingHostedService(metricsWebHostOptions.UnobservedTaskExceptionHandler);
                builder.Services.AddMetricsEndpoints(metricsWebHostOptions.EndpointOptions, configuration);
                builder.Services.AddMetricsTrackingMiddleware(metricsWebHostOptions.TrackingMiddlewareOptions,
                                                              configuration);
                builder.Services.AddMetrics(metrics);
            }

            return(builder);
        }