fix async/await warnings

This commit is contained in:
Rafsanul Hasan 2019-04-04 09:48:49 +06:00
parent fc79c43c1e
commit 5c60b6ace7
No known key found for this signature in database
GPG Key ID: 4BBF45E04D0AD72B
4 changed files with 429 additions and 436 deletions

View File

@ -1,109 +1,113 @@
using Microsoft.AspNetCore.Builder; using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Ocelot.Middleware; using Ocelot.Middleware;
using System; using System;
using HealthChecks.UI.Client; using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace OcelotApiGw namespace OcelotApiGw
{ {
public class Startup public class Startup
{ {
private readonly IConfiguration _cfg; private readonly IConfiguration _cfg;
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ => _cfg = configuration;
_cfg = configuration;
}
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
var identityUrl = _cfg.GetValue<string>("IdentityUrl"); var identityUrl = _cfg.GetValue<string>("IdentityUrl");
var authenticationProviderKey = "IdentityApiKey"; var authenticationProviderKey = "IdentityApiKey";
services.AddHealthChecks() services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy()) .AddCheck("self", () => HealthCheckResult.Healthy())
.AddUrlGroup(new Uri(_cfg["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) .AddUrlGroup(new Uri(_cfg["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
.AddUrlGroup(new Uri(_cfg["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) .AddUrlGroup(new Uri(_cfg["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
.AddUrlGroup(new Uri(_cfg["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) .AddUrlGroup(new Uri(_cfg["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
.AddUrlGroup(new Uri(_cfg["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) .AddUrlGroup(new Uri(_cfg["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
.AddUrlGroup(new Uri(_cfg["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" }) .AddUrlGroup(new Uri(_cfg["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
.AddUrlGroup(new Uri(_cfg["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }) .AddUrlGroup(new Uri(_cfg["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
.AddUrlGroup(new Uri(_cfg["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" }); .AddUrlGroup(new Uri(_cfg["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder builder => builder
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.SetIsOriginAllowed((host) => true) .SetIsOriginAllowed((host) => true)
.AllowCredentials()); .AllowCredentials());
}); });
services.AddAuthentication() services.AddAuthentication()
.AddJwtBearer(authenticationProviderKey, x => .AddJwtBearer(authenticationProviderKey, x =>
{ {
x.Authority = identityUrl; x.Authority = identityUrl;
x.RequireHttpsMetadata = false; x.RequireHttpsMetadata = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters() x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{ {
ValidAudiences = new[] { "orders", "basket", "locations", "marketing", "mobileshoppingagg", "webshoppingagg" } ValidAudiences = new[] { "orders", "basket", "locations", "marketing", "mobileshoppingagg", "webshoppingagg" }
}; };
x.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents() x.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents()
{ {
OnAuthenticationFailed = async ctx => OnAuthenticationFailed = async ctx =>
{ {
int i = 0; await Task.Run(() =>
}, {
OnTokenValidated = async ctx => });
{ },
int i = 0; OnTokenValidated = async ctx =>
}, {
await Task.Run(() =>
{
});
},
OnMessageReceived = async ctx => OnMessageReceived = async ctx =>
{ {
int i = 0; await Task.Run(() =>
} {
}; });
}); }
};
});
services.AddOcelot(_cfg); services.AddOcelot(_cfg);
} }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{ {
var pathBase = _cfg["PATH_BASE"]; var pathBase = _cfg["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
app.UsePathBase(pathBase); app.UsePathBase(pathBase);
} }
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
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");
app.UseOcelot().Wait(); app.UseOcelot().Wait();
} }
} }
} }

View File

@ -1,9 +1,7 @@
using System; using HealthChecks.UI.Client;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -13,207 +11,206 @@ using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services; using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
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 Polly; using Polly;
using Polly.Extensions.Http; using Polly.Extensions.Http;
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using HealthChecks.UI.Client; using System;
using Microsoft.AspNetCore.Diagnostics.HealthChecks; using System.Collections.Generic;
using Microsoft.Extensions.Diagnostics.HealthChecks; using System.IdentityModel.Tokens.Jwt;
using System.Net.Http;
using System.Threading.Tasks;
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
{ {
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; }
// 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.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddHealthChecks() services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy()) .AddCheck("self", () => HealthCheckResult.Healthy())
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" }) .AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }) .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" }); .AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
services.AddCustomMvc(Configuration) services.AddCustomMvc(Configuration)
.AddCustomAuthentication(Configuration) .AddCustomAuthentication(Configuration)
.AddHttpServices(); .AddHttpServices();
} }
// 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) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase); loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", 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");
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
else else
{ {
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. // 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.UseHsts();
} }
app.UseAuthentication(); app.UseAuthentication();
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseMvc(); app.UseMvc();
app.UseSwagger().UseSwaggerUI(c => app.UseSwagger().UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
c.OAuthClientId("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui"); c.OAuthClientId("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui");
c.OAuthClientSecret(string.Empty); c.OAuthClientSecret(string.Empty);
c.OAuthRealm(string.Empty); c.OAuthRealm(string.Empty);
c.OAuthAppName("Purchase BFF Swagger UI"); c.OAuthAppName("Purchase BFF Swagger UI");
}); });
} }
} }
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddOptions(); services.AddOptions();
services.Configure<UrlsConfig>(configuration.GetSection("urls")); services.Configure<UrlsConfig>(configuration.GetSection("urls"));
services.AddMvc() services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2); .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
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 = "Shopping Aggregator for Mobile Clients", Title = "Shopping Aggregator for Mobile Clients",
Version = "v1", Version = "v1",
Description = "Shopping Aggregator for Mobile Clients", Description = "Shopping Aggregator for Mobile Clients",
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>()
{ {
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" } { "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
services.AddCors(options => services.AddCors(options =>
{ {
options.AddPolicy("CorsPolicy", options.AddPolicy("CorsPolicy",
builder => builder builder => builder
.AllowAnyMethod() .AllowAnyMethod()
.AllowAnyHeader() .AllowAnyHeader()
.SetIsOriginAllowed((host) => true) .SetIsOriginAllowed((host) => true)
.AllowCredentials()); .AllowCredentials());
}); });
return services; return services;
} }
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var identityUrl = configuration.GetValue<string>("urls:identity"); var identityUrl = configuration.GetValue<string>("urls:identity");
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 = "mobileshoppingagg"; options.Audience = "mobileshoppingagg";
options.Events = new JwtBearerEvents() options.Events = new JwtBearerEvents()
{ {
OnAuthenticationFailed = async ctx => OnAuthenticationFailed = async ctx =>
{ {
}, await Task.Run(() => { });
OnTokenValidated = async ctx => },
{ OnTokenValidated = async ctx =>
} {
}; await Task.Run(() => { });
}); }
};
});
return services; return services;
} }
public static IServiceCollection AddHttpServices(this IServiceCollection services) public static IServiceCollection AddHttpServices(this IServiceCollection services)
{ {
//register delegating handlers //register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//register http services //register http services
services.AddHttpClient<IBasketService, BasketService>() services.AddHttpClient<IBasketService, BasketService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ICatalogService, CatalogService>() services.AddHttpClient<ICatalogService, CatalogService>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderApiClient, OrderApiClient>() services.AddHttpClient<IOrderApiClient, OrderApiClient>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
return services; return services;
} }
private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{ => HttpPolicyExtensions
return HttpPolicyExtensions .HandleTransientHttpError()
.HandleTransientHttpError() .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{ => HttpPolicyExtensions
return HttpPolicyExtensions .HandleTransientHttpError()
.HandleTransientHttpError() .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)); }
}
}
} }

View File

@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Authentication.JwtBearer; using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -9,212 +11,207 @@ using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure;
using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services; using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services;
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 Polly; using Polly;
using Polly.Extensions.Http; using Polly.Extensions.Http;
using Polly.Timeout;
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Net.Http; using System.Net.Http;
using HealthChecks.UI.Client; using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator
{ {
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; }
// 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.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddHealthChecks() services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy()) .AddCheck("self", () => HealthCheckResult.Healthy())
.AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) .AddUrlGroup(new Uri(Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
.AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) .AddUrlGroup(new Uri(Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
.AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) .AddUrlGroup(new Uri(Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
.AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
.AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" }) .AddUrlGroup(new Uri(Configuration["MarketingUrlHC"]), name: "marketingapi-check", tags: new string[] { "marketingapi" })
.AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }) .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" })
.AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" }); .AddUrlGroup(new Uri(Configuration["LocationUrlHC"]), name: "locationapi-check", tags: new string[] { "locationapi" });
services.AddCustomMvc(Configuration) services.AddCustomMvc(Configuration)
.AddCustomAuthentication(Configuration) .AddCustomAuthentication(Configuration)
.AddApplicationServices(); .AddApplicationServices();
} }
// 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) public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ {
var pathBase = Configuration["PATH_BASE"]; var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrEmpty(pathBase)) if (!string.IsNullOrEmpty(pathBase))
{ {
loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase); loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", 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");
if (env.IsDevelopment()) if (env.IsDevelopment())
{ {
app.UseDeveloperExceptionPage(); app.UseDeveloperExceptionPage();
} }
else else
{ {
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. // 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.UseHsts();
} }
app.UseAuthentication(); app.UseAuthentication();
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseMvc(); app.UseMvc();
app.UseSwagger() app.UseSwagger()
.UseSwaggerUI(c => .UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
//c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI"); //c.ConfigureOAuth2("Microsoft.eShopOnContainers.Web.Shopping.HttpAggregatorwaggerui", "", "", "Purchase BFF Swagger UI");
}); });
} }
} }
public static class ServiceCollectionExtensions public static class ServiceCollectionExtensions
{ {
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
{ {
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var identityUrl = configuration.GetValue<string>("urls:identity"); var identityUrl = configuration.GetValue<string>("urls:identity");
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 = "webshoppingagg"; options.Audience = "webshoppingagg";
options.Events = new JwtBearerEvents() options.Events = new JwtBearerEvents()
{ {
OnAuthenticationFailed = async ctx => OnAuthenticationFailed = async ctx =>
{ {
int i = 0; await Task.Run(() =>
}, {
OnTokenValidated = async ctx => });
{ },
int i = 0; OnTokenValidated = async ctx =>
} {
}; await Task.Run(() =>
}); {
});
}
};
});
return services; return services;
} }
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddOptions(); services.AddOptions();
services.Configure<UrlsConfig>(configuration.GetSection("urls")); services.Configure<UrlsConfig>(configuration.GetSection("urls"));
services.AddMvc() services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2); .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
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 = "Shopping Aggregator for Web Clients", Title = "Shopping Aggregator for Web Clients",
Version = "v1", Version = "v1",
Description = "Shopping Aggregator for Web Clients", Description = "Shopping Aggregator for Web Clients",
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>()
{ {
{ "webshoppingagg", "Shopping Aggregator for Web Clients" } { "webshoppingagg", "Shopping Aggregator for Web Clients" }
} }
}); });
options.OperationFilter<AuthorizeCheckOperationFilter>(); options.OperationFilter<AuthorizeCheckOperationFilter>();
}); });
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 AddApplicationServices(this IServiceCollection services) public static IServiceCollection AddApplicationServices(this IServiceCollection services)
{ {
//register delegating handlers //register delegating handlers
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//register http services //register http services
services.AddHttpClient<IBasketService, BasketService>() services.AddHttpClient<IBasketService, BasketService>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<ICatalogService, CatalogService>() services.AddHttpClient<ICatalogService, CatalogService>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
services.AddHttpClient<IOrderApiClient, OrderApiClient>() services.AddHttpClient<IOrderApiClient, OrderApiClient>()
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>() .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(GetRetryPolicy()) .AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy()); .AddPolicyHandler(GetCircuitBreakerPolicy());
return services; return services;
} }
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy() private static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{ => HttpPolicyExtensions
return HttpPolicyExtensions .HandleTransientHttpError()
.HandleTransientHttpError() .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
} private static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
=> HttpPolicyExtensions
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy() .HandleTransientHttpError()
{ .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
return HttpPolicyExtensions }
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
}
} }

View File

@ -1,16 +1,11 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Webhooks.API.IntegrationEvents namespace Webhooks.API.IntegrationEvents
{ {
public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent> public class ProductPriceChangedIntegrationEventHandler : IIntegrationEventHandler<ProductPriceChangedIntegrationEvent>
{ {
public async Task Handle(ProductPriceChangedIntegrationEvent @event) public async Task Handle(ProductPriceChangedIntegrationEvent @event)
{ => await Task.Run(() => { });
int i = 0; }
}
}
} }