fix deprecation warning

This commit is contained in:
Rafsanul Hasan 2019-04-04 10:21:57 +06:00
parent 99d47401c0
commit 52be60c905
No known key found for this signature in database
GPG Key ID: 4BBF45E04D0AD72B
2 changed files with 400 additions and 406 deletions

View File

@ -1,12 +1,4 @@
using System; using Autofac;
using System.Collections.Generic;
using System.Data.Common;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Autofac;
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
using HealthChecks.UI.Client; using HealthChecks.UI.Client;
using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility;
@ -31,342 +23,345 @@ using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using RabbitMQ.Client; using RabbitMQ.Client;
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Threading;
using Webhooks.API.Infrastructure; using Webhooks.API.Infrastructure;
using Webhooks.API.IntegrationEvents; using Webhooks.API.IntegrationEvents;
using Webhooks.API.Services; using Webhooks.API.Services;
namespace Webhooks.API namespace Webhooks.API
{ {
public class Startup public class Startup
{ {
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration) => Configuration = configuration;
{
Configuration = configuration;
}
public IServiceProvider ConfigureServices(IServiceCollection services) public IServiceProvider ConfigureServices(IServiceCollection services)
{ {
services services
.AddAppInsight(Configuration) .AddAppInsight(Configuration)
.AddCustomMVC(Configuration) .AddCustomMVC(Configuration)
.AddCustomDbContext(Configuration) .AddCustomDbContext(Configuration)
.AddSwagger(Configuration) .AddSwagger(Configuration)
.AddCustomHealthCheck(Configuration) .AddCustomHealthCheck(Configuration)
.AddHttpClientServices(Configuration) .AddHttpClientServices(Configuration)
.AddIntegrationServices(Configuration) .AddIntegrationServices(Configuration)
.AddEventBus(Configuration) .AddEventBus(Configuration)
.AddCustomAuthentication(Configuration) .AddCustomAuthentication(Configuration)
.AddSingleton<IHttpContextAccessor, HttpContextAccessor>() .AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
.AddTransient<IIdentityService, IdentityService>() .AddTransient<IIdentityService, IdentityService>()
.AddTransient<IGrantUrlTesterService, GrantUrlTesterService>() .AddTransient<IGrantUrlTesterService, GrantUrlTesterService>()
.AddTransient<IWebhooksRetriever, WebhooksRetriever>() .AddTransient<IWebhooksRetriever, WebhooksRetriever>()
.AddTransient<IWebhooksSender, WebhooksSender>(); .AddTransient<IWebhooksSender, WebhooksSender>();
var container = new ContainerBuilder(); var container = new ContainerBuilder();
container.Populate(services); container.Populate(services);
return new AutofacServiceProvider(container.Build()); return new AutofacServiceProvider(container.Build());
} }
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, ILoggingBuilder loggingBuilder)
{ {
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(loggingBuilder, options => options.IncludeScopes = true);
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'"); loggerFactory.CreateLogger("init").LogDebug($"Using PATH BASE '{pathBase}'");
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
app.UseHealthChecks("/hc", new HealthCheckOptions() app.UseHealthChecks("/hc", new HealthCheckOptions()
{ {
Predicate = _ => true, Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
}); });
app.UseHealthChecks("/liveness", new HealthCheckOptions app.UseHealthChecks("/liveness", new HealthCheckOptions
{ {
Predicate = r => r.Name.Contains("self") Predicate = r => r.Name.Contains("self")
}); });
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");
ConfigureAuth(app); ConfigureAuth(app);
app.UseMvcWithDefaultRoute(); app.UseMvcWithDefaultRoute();
app.UseSwagger() app.UseSwagger()
.UseSwaggerUI(c => .UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Webhooks.API V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Webhooks.API V1");
c.OAuthClientId("webhooksswaggerui"); c.OAuthClientId("webhooksswaggerui");
c.OAuthAppName("WebHooks Service Swagger UI"); c.OAuthAppName("WebHooks Service Swagger UI");
}); });
ConfigureEventBus(app); ConfigureEventBus(app);
} }
protected virtual void ConfigureAuth(IApplicationBuilder app) protected virtual void ConfigureAuth(IApplicationBuilder app)
{ {
/* /*
if (Configuration.GetValue<bool>("UseLoadTest")) if (Configuration.GetValue<bool>("UseLoadTest"))
{ {
app.UseMiddleware<ByPassAuthMiddleware>(); app.UseMiddleware<ByPassAuthMiddleware>();
} }
*/ */
app.UseAuthentication(); app.UseAuthentication();
} }
protected virtual void ConfigureEventBus(IApplicationBuilder app) protected virtual void ConfigureEventBus(IApplicationBuilder app)
{ {
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>(); var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>(); eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>(); eventBus.Subscribe<OrderStatusChangedToShippedIntegrationEvent, OrderStatusChangedToShippedIntegrationEventHandler>();
eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>(); eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>();
} }
} }
static class CustomExtensionMethods static class CustomExtensionMethods
{ {
public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddApplicationInsightsTelemetry(configuration); services.AddApplicationInsightsTelemetry(configuration);
var orchestratorType = configuration.GetValue<string>("OrchestratorType"); var orchestratorType = configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable K8s telemetry initializer // Enable K8s telemetry initializer
services.AddApplicationInsightsKubernetesEnricher(); services.AddApplicationInsightsKubernetesEnricher();
} }
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "SF")
{ {
// Enable SF telemetry initializer // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer()); new FabricTelemetryInitializer());
} }
return services; return services;
} }
public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddMvc(options => services.AddMvc(options =>
{ {
options.Filters.Add(typeof(HttpGlobalExceptionFilter)); options.Filters.Add(typeof(HttpGlobalExceptionFilter));
}) })
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddControllersAsServices(); .AddControllersAsServices();
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder builder => builder
.SetIsOriginAllowed((host) => true) .SetIsOriginAllowed((host) => true)
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.AllowCredentials()); .AllowCredentials());
}); });
return services; return services;
} }
public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddDbContext<WebhooksContext>(options => services.AddDbContext<WebhooksContext>(options =>
{ {
options.UseSqlServer(configuration["ConnectionString"], options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions => sqlServerOptionsAction: sqlOptions =>
{ {
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
}); });
// Changing default behavior when client evaluation occurs to throw. // Changing default behavior when client evaluation occurs to throw.
// Default in EF Core would be to log a warning when client evaluation is performed. // Default in EF Core would be to log a warning when client evaluation is performed.
options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); options.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
}); });
return services; return services;
} }
public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddSwaggerGen(options => services.AddSwaggerGen(options =>
{ {
options.DescribeAllEnumsAsStrings(); options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{ {
Title = "eShopOnContainers - Webhooks HTTP API", Title = "eShopOnContainers - Webhooks HTTP API",
Version = "v1", Version = "v1",
Description = "The Webhooks Microservice HTTP API. This is a simple webhooks CRUD registration entrypoint", Description = "The Webhooks Microservice HTTP API. This is a simple webhooks CRUD registration entrypoint",
TermsOfService = "Terms Of Service" TermsOfService = "Terms Of Service"
}); });
options.AddSecurityDefinition("oauth2", new OAuth2Scheme options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{ {
Type = "oauth2", Type = "oauth2",
Flow = "implicit", Flow = "implicit",
AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize", AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token", TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
Scopes = new Dictionary<string, string>() Scopes = new Dictionary<string, string>()
{ {
{ "webhooks", "Webhooks API" } { "webhooks", "Webhooks API" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
return services; return services;
} }
public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{ {
var subscriptionClientName = configuration["SubscriptionClientName"]; var subscriptionClientName = configuration["SubscriptionClientName"];
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IEventBus, EventBusServiceBus>(sp => services.AddSingleton<IEventBus, EventBusServiceBus>(sp =>
{ {
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>(); var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger, return new EventBusServiceBus(serviceBusPersisterConnection, logger,
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope); eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
}); });
} }
else else
{ {
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{ {
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>(); var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
var retryCount = 5; var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(configuration["EventBusRetryCount"]); retryCount = int.Parse(configuration["EventBusRetryCount"]);
} }
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
}); });
} }
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
services.AddTransient<ProductPriceChangedIntegrationEventHandler>(); services.AddTransient<ProductPriceChangedIntegrationEventHandler>();
services.AddTransient<OrderStatusChangedToShippedIntegrationEventHandler>(); services.AddTransient<OrderStatusChangedToShippedIntegrationEventHandler>();
services.AddTransient<OrderStatusChangedToPaidIntegrationEventHandler>(); services.AddTransient<OrderStatusChangedToPaidIntegrationEventHandler>();
return services; return services;
} }
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration)
{ {
var accountName = configuration.GetValue<string>("AzureStorageAccountName"); var accountName = configuration.GetValue<string>("AzureStorageAccountName");
var accountKey = configuration.GetValue<string>("AzureStorageAccountKey"); var accountKey = configuration.GetValue<string>("AzureStorageAccountKey");
var hcBuilder = services.AddHealthChecks(); var hcBuilder = services.AddHealthChecks();
hcBuilder hcBuilder
.AddCheck("self", () => HealthCheckResult.Healthy()) .AddCheck("self", () => HealthCheckResult.Healthy())
.AddSqlServer( .AddSqlServer(
configuration["ConnectionString"], configuration["ConnectionString"],
name: "WebhooksApiDb-check", name: "WebhooksApiDb-check",
tags: new string[] { "webhooksdb" }); tags: new string[] { "webhooksdb" });
return services; return services;
} }
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan); services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan);
//add http client services //add http client services
services.AddHttpClient("GrantClient") services.AddHttpClient("GrantClient")
.SetHandlerLifetime(TimeSpan.FromMinutes(5)); .SetHandlerLifetime(TimeSpan.FromMinutes(5));
//.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>(); //.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
return services; return services;
} }
public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>( services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
sp => (DbConnection c) => new IntegrationEventLogService(c)); sp => (DbConnection c) => new IntegrationEventLogService(c));
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IServiceBusPersisterConnection>(sp => services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{ {
var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
var serviceBusConnection = new ServiceBusConnectionStringBuilder(configuration["EventBusConnection"]); var serviceBusConnection = new ServiceBusConnectionStringBuilder(configuration["EventBusConnection"]);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger); return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
}); });
} }
else else
{ {
services.AddSingleton<IRabbitMQPersistentConnection>(sp => services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{ {
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory() var factory = new ConnectionFactory()
{ {
HostName = configuration["EventBusConnection"], HostName = configuration["EventBusConnection"],
DispatchConsumersAsync = true DispatchConsumersAsync = true
}; };
if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
{ {
factory.UserName = configuration["EventBusUserName"]; factory.UserName = configuration["EventBusUserName"];
} }
if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
{ {
factory.Password = configuration["EventBusPassword"]; factory.Password = configuration["EventBusPassword"];
} }
var retryCount = 5; var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(configuration["EventBusRetryCount"]); retryCount = int.Parse(configuration["EventBusRetryCount"]);
} }
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
}); });
} }
return services; return services;
} }
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
// prevent from mapping "sub" claim to nameidentifier. // prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
var identityUrl = configuration.GetValue<string>("IdentityUrl"); var identityUrl = configuration.GetValue<string>("IdentityUrl");
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => }).AddJwtBearer(options =>
{ {
options.Authority = identityUrl; options.Authority = identityUrl;
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.Audience = "webhooks"; options.Audience = "webhooks";
}); });
return services; return services;
} }
} }
} }

View File

@ -1,161 +1,160 @@
using eShopOnContainers.WebSPA; using eShopOnContainers.WebSPA;
using HealthChecks.UI.Client;
using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.ApplicationInsights.ServiceFabric;
using Microsoft.AspNetCore.Antiforgery; using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using StackExchange.Redis; using StackExchange.Redis;
using System; using System;
using System.IO; using System.IO;
using WebSPA.Infrastructure; using WebSPA.Infrastructure;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace eShopConContainers.WebSPA namespace eShopConContainers.WebSPA
{ {
public class Startup public class Startup
{ {
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ => Configuration = configuration;
Configuration = configuration;
}
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
private IHostingEnvironment _hostingEnv; private readonly IHostingEnvironment _hostingEnv;
public Startup(IHostingEnvironment env) public Startup(IHostingEnvironment env)
{ {
_hostingEnv = env; _hostingEnv = env;
var localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/"; var localPath = new Uri(Configuration["ASPNETCORE_URLS"])?.LocalPath ?? "/";
Configuration["BaseUrl"] = localPath; Configuration["BaseUrl"] = localPath;
} }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
RegisterAppInsights(services); RegisterAppInsights(services);
services.AddHealthChecks() services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy()) .AddCheck("self", () => HealthCheckResult.Healthy())
.AddUrlGroup(new Uri(Configuration["PurchaseUrlHC"]), name: "purchaseapigw-check", tags: new string[] { "purchaseapigw" }) .AddUrlGroup(new Uri(Configuration["PurchaseUrlHC"]), name: "purchaseapigw-check", tags: new string[] { "purchaseapigw" })
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapigw-check", tags: new string[] { "marketingapigw" }) .AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapigw-check", tags: new string[] { "marketingapigw" })
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }); .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" });
services.Configure<AppSettings>(Configuration); services.Configure<AppSettings>(Configuration);
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString) if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
{ {
services.AddDataProtection(opts => services.AddDataProtection(opts =>
{ {
opts.ApplicationDiscriminator = "eshop.webspa"; opts.ApplicationDiscriminator = "eshop.webspa";
}) })
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys"); .PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
} }
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN"); services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddMvc() services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options => .AddJsonOptions(options =>
{ {
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}); });
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery) public void Configure(IApplicationBuilder app, IHostingEnvironment env, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, IAntiforgery antiforgery, ILoggingBuilder loggingBuilder)
{ {
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace); ApplicationInsightsLoggingBuilderExtensions.AddApplicationInsights(loggingBuilder, options => options.IncludeScopes = true);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHealthChecks("/liveness", new HealthCheckOptions if (env.IsDevelopment())
{ {
Predicate = r => r.Name.Contains("self") app.UseDeveloperExceptionPage();
}); }
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHealthChecks("/hc", new HealthCheckOptions() app.UseHealthChecks("/liveness", new HealthCheckOptions
{ {
Predicate = _ => true, Predicate = r => r.Name.Contains("self")
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse });
});
// Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page app.UseHealthChecks("/hc", new HealthCheckOptions()
// load and passed back token on every subsequent async request {
// app.Use(async (context, next) => Predicate = _ => true,
// { ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
// if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase)) });
// {
// var tokens = antiforgery.GetAndStoreTokens(context);
// context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
// }
// await next.Invoke();
// });
//Seed Data // Configure XSRF middleware, This pattern is for SPA style applications where XSRF token is added on Index page
WebContextSeed.Seed(app, env, loggerFactory); // load and passed back token on every subsequent async request
// app.Use(async (context, next) =>
// {
// if (string.Equals(context.Request.Path.Value, "/", StringComparison.OrdinalIgnoreCase))
// {
// var tokens = antiforgery.GetAndStoreTokens(context);
// context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
// }
// await next.Invoke();
// });
var pathBase = Configuration["PATH_BASE"]; //Seed Data
if (!string.IsNullOrEmpty(pathBase)) WebContextSeed.Seed(app, env, loggerFactory);
{
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
app.Use(async (context, next) => var pathBase = Configuration["PATH_BASE"];
{ if (!string.IsNullOrEmpty(pathBase))
await next(); {
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase);
app.UsePathBase(pathBase);
}
// If there's no available file and the request doesn't contain an extension, we're probably trying to access a page. app.Use(async (context, next) =>
// Rewrite request to use app root {
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api")) await next();
{
context.Request.Path = "/index.html";
context.Response.StatusCode = 200; // Make sure we update the status code, otherwise it returns 404
await next();
}
});
app.UseDefaultFiles(); // If there's no available file and the request doesn't contain an extension, we're probably trying to access a page.
app.UseStaticFiles(); // Rewrite request to use app root
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api"))
{
context.Request.Path = "/index.html";
context.Response.StatusCode = 200; // Make sure we update the status code, otherwise it returns 404
await next();
}
});
app.UseMvcWithDefaultRoute(); app.UseDefaultFiles();
} app.UseStaticFiles();
private void RegisterAppInsights(IServiceCollection services) app.UseMvcWithDefaultRoute();
{ }
services.AddApplicationInsightsTelemetry(Configuration);
var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
if (orchestratorType?.ToUpper() == "K8S") private void RegisterAppInsights(IServiceCollection services)
{ {
// Enable K8s telemetry initializer services.AddApplicationInsightsTelemetry(Configuration);
services.AddApplicationInsightsKubernetesEnricher(); var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
}
if (orchestratorType?.ToUpper() == "SF") if (orchestratorType?.ToUpper() == "K8S")
{ {
// Enable SF telemetry initializer // Enable K8s telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => services.AddApplicationInsightsKubernetesEnricher();
new FabricTelemetryInitializer()); }
} if (orchestratorType?.ToUpper() == "SF")
} {
} // Enable SF telemetry initializer
services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
new FabricTelemetryInitializer());
}
}
}
} }