1616using Microsoft . eShopOnContainers . Mobile . Shopping . HttpAggregator . Filters . Basket . API . Infrastructure . Filters ;
1717using Microsoft . eShopOnContainers . Mobile . Shopping . HttpAggregator . Services ;
1818using Swashbuckle . AspNetCore . Swagger ;
19+ using Microsoft . eShopOnContainers . Mobile . Shopping . HttpAggregator . Infrastructure ;
20+ using Polly . Extensions . Http ;
21+ using Polly ;
1922
2023namespace Microsoft . eShopOnContainers . Mobile . Shopping . HttpAggregator
2124{
@@ -31,14 +34,47 @@ public Startup(IConfiguration configuration)
3134 // This method gets called by the runtime. Use this method to add services to the container.
3235 public void ConfigureServices ( IServiceCollection services )
3336 {
34- services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
35- services . AddSingleton < IHttpClient , StandardHttpClient > ( ) ;
36- services . AddTransient < ICatalogService , CatalogService > ( ) ;
37- services . AddTransient < IBasketService , BasketService > ( ) ;
38- services . AddTransient < IOrderApiClient , OrderApiClient > ( ) ;
37+ services . AddCustomMvc ( Configuration )
38+ . AddCustomAuthentication ( Configuration )
39+ . AddHttpServices ( ) ;
40+ }
41+
42+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
43+ public void Configure ( IApplicationBuilder app , IHostingEnvironment env , ILoggerFactory loggerFactory )
44+ {
45+ var pathBase = Configuration [ "PATH_BASE" ] ;
46+
47+ if ( ! string . IsNullOrEmpty ( pathBase ) )
48+ {
49+ loggerFactory . CreateLogger ( "init" ) . LogDebug ( $ "Using PATH BASE '{ pathBase } '") ;
50+ app . UsePathBase ( pathBase ) ;
51+ }
52+
53+ app . UseCors ( "CorsPolicy" ) ;
54+
55+ if ( env . IsDevelopment ( ) )
56+ {
57+ app . UseDeveloperExceptionPage ( ) ;
58+ }
59+
60+ app . UseAuthentication ( ) ;
61+
62+ app . UseMvc ( ) ;
63+
64+ app . UseSwagger ( ) . UseSwaggerUI ( c =>
65+ {
66+ c . SwaggerEndpoint ( $ "{ ( ! string . IsNullOrEmpty ( pathBase ) ? pathBase : string . Empty ) } /swagger/v1/swagger.json", "Purchase BFF V1" ) ;
67+ c . ConfigureOAuth2 ( "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui" , "" , "" , "Purchase BFF Swagger UI" ) ;
68+ } ) ;
69+ }
70+ }
3971
72+ public static class ServiceCollectionExtensions
73+ {
74+ public static IServiceCollection AddCustomMvc ( this IServiceCollection services , IConfiguration configuration )
75+ {
4076 services . AddOptions ( ) ;
41- services . Configure < UrlsConfig > ( Configuration . GetSection ( "urls" ) ) ;
77+ services . Configure < UrlsConfig > ( configuration . GetSection ( "urls" ) ) ;
4278
4379 services . AddMvc ( ) ;
4480
@@ -57,8 +93,8 @@ public void ConfigureServices(IServiceCollection services)
5793 {
5894 Type = "oauth2" ,
5995 Flow = "implicit" ,
60- AuthorizationUrl = $ "{ Configuration . GetValue < string > ( "IdentityUrlExternal" ) } /connect/authorize",
61- TokenUrl = $ "{ Configuration . GetValue < string > ( "IdentityUrlExternal" ) } /connect/token",
96+ AuthorizationUrl = $ "{ configuration . GetValue < string > ( "IdentityUrlExternal" ) } /connect/authorize",
97+ TokenUrl = $ "{ configuration . GetValue < string > ( "IdentityUrlExternal" ) } /connect/token",
6298 Scopes = new Dictionary < string , string > ( )
6399 {
64100 { "mobileshoppingagg" , "Shopping Aggregator for Mobile Clients" }
@@ -77,9 +113,12 @@ public void ConfigureServices(IServiceCollection services)
77113 . AllowCredentials ( ) ) ;
78114 } ) ;
79115
80-
116+ return services ;
117+ }
118+ public static IServiceCollection AddCustomAuthentication ( this IServiceCollection services , IConfiguration configuration )
119+ {
81120 JwtSecurityTokenHandler . DefaultInboundClaimTypeMap . Clear ( ) ;
82- var identityUrl = Configuration . GetValue < string > ( "urls:identity" ) ;
121+ var identityUrl = configuration . GetValue < string > ( "urls:identity" ) ;
83122 services . AddAuthentication ( options =>
84123 {
85124 options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
@@ -102,37 +141,40 @@ public void ConfigureServices(IServiceCollection services)
102141 }
103142 } ;
104143 } ) ;
105- }
106144
107- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
108- public void Configure ( IApplicationBuilder app , IHostingEnvironment env , ILoggerFactory loggerFactory )
145+ return services ;
146+ }
147+ public static IServiceCollection AddHttpServices ( this IServiceCollection services )
109148 {
149+ //register delegating handlers
150+ services . AddTransient < HttpClientAuthorizationDelegatingHandler > ( ) ;
151+ services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
110152
111- var pathBase = Configuration [ "PATH_BASE" ] ;
112- if ( ! string . IsNullOrEmpty ( pathBase ) )
113- {
114- loggerFactory . CreateLogger ( "init" ) . LogDebug ( $ "Using PATH BASE '{ pathBase } '") ;
115- app . UsePathBase ( pathBase ) ;
116- }
153+ //register http services
154+ var retriesWithExponentialBackoff = HttpPolicyExtensions
155+ . HandleTransientHttpError ( )
156+ . WaitAndRetryAsync ( 7 , retryAttempt => TimeSpan . FromSeconds ( Math . Pow ( 2 , retryAttempt ) ) ) ;
117157
118- app . UseCors ( "CorsPolicy" ) ;
158+ var circuitBreaker = HttpPolicyExtensions
159+ . HandleTransientHttpError ( )
160+ . CircuitBreakerAsync ( 6 , TimeSpan . FromSeconds ( 30 ) ) ;
119161
120- if ( env . IsDevelopment ( ) )
121- {
122- app . UseDeveloperExceptionPage ( ) ;
123- }
162+ services . AddHttpClient < IBasketService , BasketService > ( )
163+ . AddHttpMessageHandler < HttpClientAuthorizationDelegatingHandler > ( )
164+ . AddPolicyHandler ( retriesWithExponentialBackoff )
165+ . AddPolicyHandler ( circuitBreaker ) ;
124166
125- app . UseAuthentication ( ) ;
167+ services . AddHttpClient < ICatalogService , CatalogService > ( )
168+ . AddPolicyHandler ( retriesWithExponentialBackoff )
169+ . AddPolicyHandler ( circuitBreaker ) ;
126170
127- app . UseMvc ( ) ;
171+ services . AddHttpClient < IOrderApiClient , OrderApiClient > ( )
172+ . AddPolicyHandler ( retriesWithExponentialBackoff )
173+ . AddPolicyHandler ( circuitBreaker ) ;
128174
129- app . UseSwagger ( ) . UseSwaggerUI ( c =>
130- {
131- c . SwaggerEndpoint ( $ "{ ( ! string . IsNullOrEmpty ( pathBase ) ? pathBase : string . Empty ) } /swagger/v1/swagger.json", "Purchase BFF V1" ) ;
132- c . ConfigureOAuth2 ( "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui" , "" , "" , "Purchase BFF Swagger UI" ) ;
133- } ) ;
134175
135176
177+ return services ;
136178 }
137179 }
138180}
0 commit comments