Merge pull request #2092 from erjain/update/webshoppingagg-webap-builder
Update/webshoppingagg webapp builder
This commit is contained in:
		
						commit
						9d38de0c83
					
				| @ -38,3 +38,4 @@ global using System.Threading.Tasks; | |||||||
| global using System.Threading; | global using System.Threading; | ||||||
| global using System; | global using System; | ||||||
| global using Microsoft.IdentityModel.Tokens; | global using Microsoft.IdentityModel.Tokens; | ||||||
|  | global using Serilog.Context; | ||||||
| @ -1,24 +1,208 @@ | |||||||
| await BuildWebHost(args).RunAsync(); | var appName = "Web.Shopping.HttpAggregator"; | ||||||
|  | var builder = WebApplication.CreateBuilder(args); | ||||||
| 
 | 
 | ||||||
| IWebHost BuildWebHost(string[] args) => | builder.Host.UseSerilog(CreateSerilogLogger(builder.Configuration)); | ||||||
|     WebHost | builder.Services.AddHealthChecks() | ||||||
|         .CreateDefaultBuilder(args) |     .AddCheck("self", () => HealthCheckResult.Healthy()) | ||||||
|         .ConfigureAppConfiguration(cb => |     .AddUrlGroup(new Uri(builder.Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" }) | ||||||
|  |     .AddUrlGroup(new Uri(builder.Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" }) | ||||||
|  |     .AddUrlGroup(new Uri(builder.Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) | ||||||
|  |     .AddUrlGroup(new Uri(builder.Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) | ||||||
|  |     .AddUrlGroup(new Uri(builder.Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); | ||||||
|  | builder.Services.AddCustomMvc(builder.Configuration) | ||||||
|  |     .AddCustomAuthentication(builder.Configuration) | ||||||
|  |     .AddApplicationServices() | ||||||
|  |     .AddGrpcServices(); | ||||||
|  | var app = builder.Build(); | ||||||
|  | if (app.Environment.IsDevelopment()) | ||||||
|  | { | ||||||
|  |     app.UseDeveloperExceptionPage(); | ||||||
|  | } | ||||||
|  | else | ||||||
|  | { | ||||||
|  |     app.UseExceptionHandler("/Home/Error"); | ||||||
|  | } | ||||||
|  | var pathBase = builder.Configuration["PATH_BASE"]; | ||||||
|  | if (!string.IsNullOrEmpty(pathBase)) | ||||||
|  | { | ||||||
|  |     app.UsePathBase(pathBase); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | app.UseHttpsRedirection(); | ||||||
|  | 
 | ||||||
|  | app.UseSwagger().UseSwaggerUI(c => | ||||||
|  | { | ||||||
|  |     c.SwaggerEndpoint($"{(!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty)}/swagger/v1/swagger.json", "Purchase BFF V1"); | ||||||
|  | 
 | ||||||
|  |     c.OAuthClientId("webshoppingaggswaggerui"); | ||||||
|  |     c.OAuthClientSecret(string.Empty); | ||||||
|  |     c.OAuthRealm(string.Empty); | ||||||
|  |     c.OAuthAppName("web shopping bff Swagger UI"); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | app.UseRouting(); | ||||||
|  | app.UseCors("CorsPolicy"); | ||||||
|  | app.UseAuthentication(); | ||||||
|  | app.UseAuthorization(); | ||||||
|  | 
 | ||||||
|  | app.MapDefaultControllerRoute(); | ||||||
|  | app.MapControllers(); | ||||||
|  | app.MapHealthChecks("/hc", new HealthCheckOptions() | ||||||
|  | { | ||||||
|  |     Predicate = _ => true, | ||||||
|  |     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | ||||||
|  | }); | ||||||
|  | app.MapHealthChecks("/liveness", new HealthCheckOptions | ||||||
|  | { | ||||||
|  |     Predicate = r => r.Name.Contains("self") | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | try | ||||||
|  | { | ||||||
|  |     Log.Information("Starts Web Application ({ApplicationContext})...", Program.AppName); | ||||||
|  |     await app.RunAsync(); | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | catch (Exception ex) | ||||||
|  | { | ||||||
|  |     Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName); | ||||||
|  |     return 1; | ||||||
|  | } | ||||||
|  | finally | ||||||
|  | { | ||||||
|  |     Log.CloseAndFlush(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) | ||||||
|  | { | ||||||
|  |     var seqServerUrl = configuration["Serilog:SeqServerUrl"]; | ||||||
|  |     var logstashUrl = configuration["Serilog:LogstashgUrl"]; | ||||||
|  |     return new LoggerConfiguration() | ||||||
|  |         .MinimumLevel.Verbose() | ||||||
|  |         .Enrich.WithProperty("ApplicationContext", Program.AppName) | ||||||
|  |         .Enrich.FromLogContext() | ||||||
|  |         .WriteTo.Console() | ||||||
|  |         .ReadFrom.Configuration(configuration) | ||||||
|  |         .CreateLogger(); | ||||||
|  | } | ||||||
|  | public partial class Program | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |     public static string Namespace = typeof(Program).Assembly.GetName().Name; | ||||||
|  |     public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | public static class ServiceCollectionExtensions | ||||||
|  | { | ||||||
|  |     public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) | ||||||
|  |     { | ||||||
|  |         JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); | ||||||
|  | 
 | ||||||
|  |         var identityUrl = configuration.GetValue<string>("urls:identity"); | ||||||
|  |         services.AddAuthentication("Bearer") | ||||||
|  |         .AddJwtBearer(options => | ||||||
|         { |         { | ||||||
|             var sources = cb.Sources; |             options.Authority = identityUrl; | ||||||
|             sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() |             options.RequireHttpsMetadata = false; | ||||||
|  |             options.Audience = "webshoppingagg"; | ||||||
|  |             options.TokenValidationParameters = new TokenValidationParameters | ||||||
|             { |             { | ||||||
|                 Optional = true, |                 ValidateAudience = false | ||||||
|                 Path = "appsettings.localhost.json", |             }; | ||||||
|                 ReloadOnChange = false |         }); | ||||||
|             }); | 
 | ||||||
|         }) |         return services; | ||||||
|         .UseStartup<Startup>() |     } | ||||||
|         .UseSerilog((builderContext, config) => |     public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) | ||||||
|  |     { | ||||||
|  |         services.AddOptions(); | ||||||
|  |         services.Configure<UrlsConfig>(configuration.GetSection("urls")); | ||||||
|  | 
 | ||||||
|  |         services.AddControllers() | ||||||
|  |                 .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); | ||||||
|  | 
 | ||||||
|  |         services.AddSwaggerGen(options => | ||||||
|         { |         { | ||||||
|             config |             options.SwaggerDoc("v1", new OpenApiInfo | ||||||
|                 .MinimumLevel.Information() |             { | ||||||
|                 .Enrich.FromLogContext() |                 Title = "Shopping Aggregator for Web Clients", | ||||||
|                 .WriteTo.Console(); |                 Version = "v1", | ||||||
|         }) |                 Description = "Shopping Aggregator for Web Clients" | ||||||
|         .Build(); |             }); | ||||||
|  |             options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme | ||||||
|  |             { | ||||||
|  |                 Type = SecuritySchemeType.OAuth2, | ||||||
|  |                 Flows = new OpenApiOAuthFlows() | ||||||
|  |                 { | ||||||
|  |                     Implicit = new OpenApiOAuthFlow() | ||||||
|  |                     { | ||||||
|  |                         AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"), | ||||||
|  |                         TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"), | ||||||
|  |                         Scopes = new Dictionary<string, string>() | ||||||
|  |                         { | ||||||
|  |                             { "webshoppingagg", "Shopping Aggregator for Web Clients" } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             options.OperationFilter<AuthorizeCheckOperationFilter>(); | ||||||
|  |         }); | ||||||
|  |         services.AddCors(options => | ||||||
|  |         { | ||||||
|  |             options.AddPolicy("CorsPolicy", | ||||||
|  |                 builder => builder | ||||||
|  |                 .SetIsOriginAllowed((host) => true) | ||||||
|  |                 .AllowAnyMethod() | ||||||
|  |                 .AllowAnyHeader() | ||||||
|  |                 .AllowCredentials()); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         return services; | ||||||
|  |     } | ||||||
|  |     public static IServiceCollection AddApplicationServices(this IServiceCollection services) | ||||||
|  |     { | ||||||
|  |         //register delegating handlers | ||||||
|  |         services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); | ||||||
|  |         services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | ||||||
|  | 
 | ||||||
|  |         //register http services | ||||||
|  | 
 | ||||||
|  |         services.AddHttpClient<IOrderApiClient, OrderApiClient>() | ||||||
|  |             .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>(); | ||||||
|  | 
 | ||||||
|  |         return services; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static IServiceCollection AddGrpcServices(this IServiceCollection services) | ||||||
|  |     { | ||||||
|  |         services.AddTransient<GrpcExceptionInterceptor>(); | ||||||
|  | 
 | ||||||
|  |         services.AddScoped<IBasketService, BasketService>(); | ||||||
|  | 
 | ||||||
|  |         services.AddGrpcClient<Basket.BasketClient>((services, options) => | ||||||
|  |         { | ||||||
|  |             var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket; | ||||||
|  |             options.Address = new Uri(basketApi); | ||||||
|  |         }).AddInterceptor<GrpcExceptionInterceptor>(); | ||||||
|  | 
 | ||||||
|  |         services.AddScoped<ICatalogService, CatalogService>(); | ||||||
|  | 
 | ||||||
|  |         services.AddGrpcClient<Catalog.CatalogClient>((services, options) => | ||||||
|  |         { | ||||||
|  |             var catalogApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcCatalog; | ||||||
|  |             options.Address = new Uri(catalogApi); | ||||||
|  |         }).AddInterceptor<GrpcExceptionInterceptor>(); | ||||||
|  | 
 | ||||||
|  |         services.AddScoped<IOrderingService, OrderingService>(); | ||||||
|  | 
 | ||||||
|  |         services.AddGrpcClient<OrderingGrpc.OrderingGrpcClient>((services, options) => | ||||||
|  |         { | ||||||
|  |             var orderingApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcOrdering; | ||||||
|  |             options.Address = new Uri(orderingApi); | ||||||
|  |         }).AddInterceptor<GrpcExceptionInterceptor>(); | ||||||
|  | 
 | ||||||
|  |         return services; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,196 +0,0 @@ | |||||||
| namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator; |  | ||||||
| 
 |  | ||||||
| public class Startup |  | ||||||
| { |  | ||||||
|     public Startup(IConfiguration configuration) |  | ||||||
|     { |  | ||||||
|         Configuration = configuration; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public IConfiguration Configuration { get; } |  | ||||||
| 
 |  | ||||||
|     // This method gets called by the runtime. Use this method to add services to the container. |  | ||||||
|     public void ConfigureServices(IServiceCollection services) |  | ||||||
|     { |  | ||||||
|         services.AddHealthChecks() |  | ||||||
|             .AddCheck("self", () => HealthCheckResult.Healthy()) |  | ||||||
|             .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["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" }) |  | ||||||
|             .AddUrlGroup(new Uri(Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" }) |  | ||||||
|             .AddUrlGroup(new Uri(Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" }); |  | ||||||
| 
 |  | ||||||
|         services.AddCustomMvc(Configuration) |  | ||||||
|             .AddCustomAuthentication(Configuration) |  | ||||||
|             //.AddCustomAuthorization(Configuration) |  | ||||||
|             .AddApplicationServices() |  | ||||||
|             .AddGrpcServices(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. |  | ||||||
|     public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) |  | ||||||
|     { |  | ||||||
|         var pathBase = Configuration["PATH_BASE"]; |  | ||||||
|         if (!string.IsNullOrEmpty(pathBase)) |  | ||||||
|         { |  | ||||||
|             loggerFactory.CreateLogger<Startup>().LogDebug("Using PATH BASE '{pathBase}'", pathBase); |  | ||||||
|             app.UsePathBase(pathBase); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (env.IsDevelopment()) |  | ||||||
|         { |  | ||||||
|             app.UseDeveloperExceptionPage(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         app.UseHttpsRedirection(); |  | ||||||
| 
 |  | ||||||
|         app.UseSwagger().UseSwaggerUI(c => |  | ||||||
|         { |  | ||||||
|             c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1"); |  | ||||||
| 
 |  | ||||||
|             c.OAuthClientId("webshoppingaggswaggerui"); |  | ||||||
|             c.OAuthClientSecret(string.Empty); |  | ||||||
|             c.OAuthRealm(string.Empty); |  | ||||||
|             c.OAuthAppName("web shopping bff Swagger UI"); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         app.UseRouting(); |  | ||||||
|         app.UseCors("CorsPolicy"); |  | ||||||
|         app.UseAuthentication(); |  | ||||||
|         app.UseAuthorization(); |  | ||||||
| 
 |  | ||||||
|         app.UseEndpoints(endpoints => |  | ||||||
|         { |  | ||||||
|             endpoints.MapDefaultControllerRoute(); |  | ||||||
|             endpoints.MapControllers(); |  | ||||||
|             endpoints.MapHealthChecks("/hc", new HealthCheckOptions() |  | ||||||
|             { |  | ||||||
|                 Predicate = _ => true, |  | ||||||
|                 ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse |  | ||||||
|             }); |  | ||||||
|             endpoints.MapHealthChecks("/liveness", new HealthCheckOptions |  | ||||||
|             { |  | ||||||
|                 Predicate = r => r.Name.Contains("self") |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| public static class ServiceCollectionExtensions |  | ||||||
| { |  | ||||||
|     public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) |  | ||||||
|     { |  | ||||||
|         JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); |  | ||||||
| 
 |  | ||||||
|         var identityUrl = configuration.GetValue<string>("urls:identity"); |  | ||||||
|         services.AddAuthentication("Bearer") |  | ||||||
|         .AddJwtBearer(options => |  | ||||||
|         { |  | ||||||
|             options.Authority = identityUrl; |  | ||||||
|             options.RequireHttpsMetadata = false; |  | ||||||
|             options.Audience = "webshoppingagg"; |  | ||||||
|             options.TokenValidationParameters = new TokenValidationParameters |  | ||||||
|             { |  | ||||||
|                 ValidateAudience = false |  | ||||||
|             }; |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         return services; |  | ||||||
|     } |  | ||||||
|     public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) |  | ||||||
|     { |  | ||||||
|         services.AddOptions(); |  | ||||||
|         services.Configure<UrlsConfig>(configuration.GetSection("urls")); |  | ||||||
| 
 |  | ||||||
|         services.AddControllers() |  | ||||||
|                 .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); |  | ||||||
| 
 |  | ||||||
|         services.AddSwaggerGen(options => |  | ||||||
|         { |  | ||||||
|             //options.DescribeAllEnumsAsStrings(); |  | ||||||
| 
 |  | ||||||
|             options.SwaggerDoc("v1", new OpenApiInfo |  | ||||||
|             { |  | ||||||
|                 Title = "Shopping Aggregator for Web Clients", |  | ||||||
|                 Version = "v1", |  | ||||||
|                 Description = "Shopping Aggregator for Web Clients" |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme |  | ||||||
|             { |  | ||||||
|                 Type = SecuritySchemeType.OAuth2, |  | ||||||
|                 Flows = new OpenApiOAuthFlows() |  | ||||||
|                 { |  | ||||||
|                     Implicit = new OpenApiOAuthFlow() |  | ||||||
|                     { |  | ||||||
|                         AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"), |  | ||||||
|                         TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"), |  | ||||||
| 
 |  | ||||||
|                         Scopes = new Dictionary<string, string>() |  | ||||||
|                         { |  | ||||||
|                             { "webshoppingagg", "Shopping Aggregator for Web Clients" } |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             options.OperationFilter<AuthorizeCheckOperationFilter>(); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         services.AddCors(options => |  | ||||||
|         { |  | ||||||
|             options.AddPolicy("CorsPolicy", |  | ||||||
|                 builder => builder |  | ||||||
|                 .SetIsOriginAllowed((host) => true) |  | ||||||
|                 .AllowAnyMethod() |  | ||||||
|                 .AllowAnyHeader() |  | ||||||
|                 .AllowCredentials()); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         return services; |  | ||||||
|     } |  | ||||||
|     public static IServiceCollection AddApplicationServices(this IServiceCollection services) |  | ||||||
|     { |  | ||||||
|         //register delegating handlers |  | ||||||
|         services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); |  | ||||||
|         services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |  | ||||||
| 
 |  | ||||||
|         //register http services |  | ||||||
| 
 |  | ||||||
|         services.AddHttpClient<IOrderApiClient, OrderApiClient>() |  | ||||||
|             .AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>(); |  | ||||||
| 
 |  | ||||||
|         return services; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public static IServiceCollection AddGrpcServices(this IServiceCollection services) |  | ||||||
|     { |  | ||||||
|         services.AddTransient<GrpcExceptionInterceptor>(); |  | ||||||
| 
 |  | ||||||
|         services.AddScoped<IBasketService, BasketService>(); |  | ||||||
| 
 |  | ||||||
|         services.AddGrpcClient<Basket.BasketClient>((services, options) => |  | ||||||
|         { |  | ||||||
|             var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket; |  | ||||||
|             options.Address = new Uri(basketApi); |  | ||||||
|         }).AddInterceptor<GrpcExceptionInterceptor>(); |  | ||||||
| 
 |  | ||||||
|         services.AddScoped<ICatalogService, CatalogService>(); |  | ||||||
| 
 |  | ||||||
|         services.AddGrpcClient<Catalog.CatalogClient>((services, options) => |  | ||||||
|         { |  | ||||||
|             var catalogApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcCatalog; |  | ||||||
|             options.Address = new Uri(catalogApi); |  | ||||||
|         }).AddInterceptor<GrpcExceptionInterceptor>(); |  | ||||||
| 
 |  | ||||||
|         services.AddScoped<IOrderingService, OrderingService>(); |  | ||||||
| 
 |  | ||||||
|         services.AddGrpcClient<OrderingGrpc.OrderingGrpcClient>((services, options) => |  | ||||||
|         { |  | ||||||
|             var orderingApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcOrdering; |  | ||||||
|             options.Address = new Uri(orderingApi); |  | ||||||
|         }).AddInterceptor<GrpcExceptionInterceptor>(); |  | ||||||
| 
 |  | ||||||
|         return services; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user