Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

Commit 52fb849

Browse files
committed
WebShopping-Agg: migrate to WebApplicationBuilder
1 parent 7d06508 commit 52fb849

File tree

3 files changed

+211
-215
lines changed

3 files changed

+211
-215
lines changed

src/ApiGateways/Web.Bff.Shopping/aggregator/GlobalUsings.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@
3838
global using System.Threading;
3939
global using System;
4040
global using Microsoft.IdentityModel.Tokens;
41+
global using Serilog.Context;
Lines changed: 210 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,215 @@
1-
await BuildWebHost(args).RunAsync();
1+
var appName = "Ordering.API";
2+
var builder = WebApplication.CreateBuilder(args);
3+
builder.WebHost.ConfigureAppConfiguration(cb => {
4+
var sources = cb.Sources;
5+
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource() {
6+
Optional = true,
7+
Path = "appsettings.localhost.json",
8+
ReloadOnChange = false
9+
});
10+
});
11+
builder.Host.UseSerilog(CreateSerilogLogger(builder.Configuration));
12+
builder.Services.AddHealthChecks()
13+
.AddCheck("self", () => HealthCheckResult.Healthy())
14+
.AddUrlGroup(new Uri(builder.Configuration["CatalogUrlHC"]), name: "catalogapi-check", tags: new string[] { "catalogapi" })
15+
.AddUrlGroup(new Uri(builder.Configuration["OrderingUrlHC"]), name: "orderingapi-check", tags: new string[] { "orderingapi" })
16+
.AddUrlGroup(new Uri(builder.Configuration["BasketUrlHC"]), name: "basketapi-check", tags: new string[] { "basketapi" })
17+
.AddUrlGroup(new Uri(builder.Configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" })
18+
.AddUrlGroup(new Uri(builder.Configuration["PaymentUrlHC"]), name: "paymentapi-check", tags: new string[] { "paymentapi" });
19+
builder.Services.AddCustomMvc(builder.Configuration)
20+
.AddCustomAuthentication(builder.Configuration)
21+
//.AddCustomAuthorization(Configuration)
22+
.AddApplicationServices()
23+
.AddGrpcServices();
24+
var app = builder.Build();
25+
if (app.Environment.IsDevelopment()) {
26+
app.UseDeveloperExceptionPage();
27+
}
28+
else {
29+
app.UseExceptionHandler("/Home/Error");
30+
}
31+
var pathBase = builder.Configuration["PATH_BASE"];
32+
if (!string.IsNullOrEmpty(pathBase)) {
33+
app.UsePathBase(pathBase);
34+
}
235

3-
IWebHost BuildWebHost(string[] args) =>
4-
WebHost
5-
.CreateDefaultBuilder(args)
6-
.ConfigureAppConfiguration(cb =>
36+
app.UseHttpsRedirection();
37+
38+
app.UseSwagger().UseSwaggerUI(c =>
39+
{
40+
c.SwaggerEndpoint($"{(!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty)}/swagger/v1/swagger.json", "Purchase BFF V1");
41+
42+
c.OAuthClientId("webshoppingaggswaggerui");
43+
c.OAuthClientSecret(string.Empty);
44+
c.OAuthRealm(string.Empty);
45+
c.OAuthAppName("web shopping bff Swagger UI");
46+
});
47+
48+
app.UseRouting();
49+
app.UseCors("CorsPolicy");
50+
app.UseAuthentication();
51+
app.UseAuthorization();
52+
53+
app.MapDefaultControllerRoute();
54+
app.MapControllers();
55+
app.MapHealthChecks("/hc", new HealthCheckOptions() {
56+
Predicate = _ => true,
57+
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
58+
});
59+
app.MapHealthChecks("/liveness", new HealthCheckOptions {
60+
Predicate = r => r.Name.Contains("self")
61+
});
62+
63+
try {
64+
65+
Log.Information("Starts Web Application ({ApplicationContext})...", Program.AppName);
66+
await app.RunAsync();
67+
68+
return 0;
69+
}
70+
catch (Exception ex) {
71+
Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName);
72+
return 1;
73+
}
74+
finally {
75+
Log.CloseAndFlush();
76+
}
77+
78+
79+
Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) {
80+
var seqServerUrl = configuration["Serilog:SeqServerUrl"];
81+
var logstashUrl = configuration["Serilog:LogstashgUrl"];
82+
return new LoggerConfiguration()
83+
.MinimumLevel.Verbose()
84+
.Enrich.WithProperty("ApplicationContext", Program.AppName)
85+
.Enrich.FromLogContext()
86+
.WriteTo.Console()
87+
//.WriteTo.Seq(string.IsNullOrWhiteSpace(seqServerUrl) ? "http://seq" : seqServerUrl)
88+
//.WriteTo.Http(string.IsNullOrWhiteSpace(logstashUrl) ? "http://logstash:8080" : logstashUrl, null)
89+
.ReadFrom.Configuration(configuration)
90+
.CreateLogger();
91+
}
92+
public partial class Program {
93+
94+
public static string Namespace = typeof(Program).Assembly.GetName().Name;
95+
public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1);
96+
}
97+
98+
public static class ServiceCollectionExtensions
99+
{
100+
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
101+
{
102+
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
103+
104+
var identityUrl = configuration.GetValue<string>("urls:identity");
105+
services.AddAuthentication("Bearer")
106+
.AddJwtBearer(options =>
7107
{
8-
var sources = cb.Sources;
9-
sources.Insert(3, new Microsoft.Extensions.Configuration.Json.JsonConfigurationSource()
108+
options.Authority = identityUrl;
109+
options.RequireHttpsMetadata = false;
110+
options.Audience = "webshoppingagg";
111+
options.TokenValidationParameters = new TokenValidationParameters
112+
{
113+
ValidateAudience = false
114+
};
115+
});
116+
117+
return services;
118+
}
119+
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
120+
{
121+
services.AddOptions();
122+
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
123+
124+
services.AddControllers()
125+
.AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);
126+
127+
services.AddSwaggerGen(options =>
128+
{
129+
//options.DescribeAllEnumsAsStrings();
130+
131+
options.SwaggerDoc("v1", new OpenApiInfo
132+
{
133+
Title = "Shopping Aggregator for Web Clients",
134+
Version = "v1",
135+
Description = "Shopping Aggregator for Web Clients"
136+
});
137+
138+
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
10139
{
11-
Optional = true,
12-
Path = "appsettings.localhost.json",
13-
ReloadOnChange = false
140+
Type = SecuritySchemeType.OAuth2,
141+
Flows = new OpenApiOAuthFlows()
142+
{
143+
Implicit = new OpenApiOAuthFlow()
144+
{
145+
AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
146+
TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
147+
148+
Scopes = new Dictionary<string, string>()
149+
{
150+
{ "webshoppingagg", "Shopping Aggregator for Web Clients" }
151+
}
152+
}
153+
}
14154
});
15-
})
16-
.UseStartup<Startup>()
17-
.UseSerilog((builderContext, config) =>
155+
156+
options.OperationFilter<AuthorizeCheckOperationFilter>();
157+
});
158+
159+
services.AddCors(options =>
18160
{
19-
config
20-
.MinimumLevel.Information()
21-
.Enrich.FromLogContext()
22-
.WriteTo.Console();
23-
})
24-
.Build();
161+
options.AddPolicy("CorsPolicy",
162+
builder => builder
163+
.SetIsOriginAllowed((host) => true)
164+
.AllowAnyMethod()
165+
.AllowAnyHeader()
166+
.AllowCredentials());
167+
});
168+
169+
return services;
170+
}
171+
public static IServiceCollection AddApplicationServices(this IServiceCollection services)
172+
{
173+
//register delegating handlers
174+
services.AddTransient<HttpClientAuthorizationDelegatingHandler>();
175+
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
176+
177+
//register http services
178+
179+
services.AddHttpClient<IOrderApiClient, OrderApiClient>()
180+
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
181+
182+
return services;
183+
}
184+
185+
public static IServiceCollection AddGrpcServices(this IServiceCollection services)
186+
{
187+
services.AddTransient<GrpcExceptionInterceptor>();
188+
189+
services.AddScoped<IBasketService, BasketService>();
190+
191+
services.AddGrpcClient<Basket.BasketClient>((services, options) =>
192+
{
193+
var basketApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcBasket;
194+
options.Address = new Uri(basketApi);
195+
}).AddInterceptor<GrpcExceptionInterceptor>();
196+
197+
services.AddScoped<ICatalogService, CatalogService>();
198+
199+
services.AddGrpcClient<Catalog.CatalogClient>((services, options) =>
200+
{
201+
var catalogApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcCatalog;
202+
options.Address = new Uri(catalogApi);
203+
}).AddInterceptor<GrpcExceptionInterceptor>();
204+
205+
services.AddScoped<IOrderingService, OrderingService>();
206+
207+
services.AddGrpcClient<OrderingGrpc.OrderingGrpcClient>((services, options) =>
208+
{
209+
var orderingApi = services.GetRequiredService<IOptions<UrlsConfig>>().Value.GrpcOrdering;
210+
options.Address = new Uri(orderingApi);
211+
}).AddInterceptor<GrpcExceptionInterceptor>();
212+
213+
return services;
214+
}
215+
}

0 commit comments

Comments
 (0)