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