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