Added sample for use new IHttpClientFactory feature on WebMVC
This commit is contained in:
parent
36fb20acea
commit
cf4b7ff47f
@ -71,7 +71,6 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
{
|
||||
var user = _appUserParser.Parse(HttpContext.User);
|
||||
await _basketSvc.AddItemToBasket(user, productDetails.Id);
|
||||
//await _basketSvc.AddItemToBasket(user, product);
|
||||
}
|
||||
return RedirectToAction("Index", "Catalog");
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WebMVC.Infrastructure
|
||||
{
|
||||
public class HttpClientAuthorizationDelegatingHandler
|
||||
: DelegatingHandler
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAccesor;
|
||||
|
||||
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
|
||||
{
|
||||
_httpContextAccesor = httpContextAccesor;
|
||||
}
|
||||
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var authorizationHeader = _httpContextAccesor.HttpContext
|
||||
.Request.Headers["Authorization"];
|
||||
|
||||
if (!string.IsNullOrEmpty(authorizationHeader))
|
||||
{
|
||||
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
|
||||
}
|
||||
|
||||
var token = await GetToken();
|
||||
|
||||
if (token != null)
|
||||
{
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||
}
|
||||
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
|
||||
async Task<string> GetToken()
|
||||
{
|
||||
const string ACCESS_TOKEN = "access_token";
|
||||
|
||||
return await _httpContextAccesor.HttpContext
|
||||
.GetTokenAsync(ACCESS_TOKEN);
|
||||
}
|
||||
}
|
||||
}
|
60
src/Web/WebMVC/Infrastructure/HttpClientDefaultPolicies.cs
Normal file
60
src/Web/WebMVC/Infrastructure/HttpClientDefaultPolicies.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Polly;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace WebMVC.Infrastructure
|
||||
{
|
||||
public class HttpClientDefaultPolicies
|
||||
{
|
||||
const int RETRY_COUNT = 6;
|
||||
const int EXCEPTIONS_ALLOWED_BEFORE_CIRCUIT_BREAKER = 5;
|
||||
|
||||
private readonly ILogger<HttpClientDefaultPolicies> _logger;
|
||||
|
||||
public HttpClientDefaultPolicies(ILogger<HttpClientDefaultPolicies> logger)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
public Policy GetWaitAndRetryPolicy()
|
||||
{
|
||||
return Policy.Handle<HttpRequestException>()
|
||||
.WaitAndRetryAsync(
|
||||
// number of retries
|
||||
RETRY_COUNT,
|
||||
// exponential backofff
|
||||
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
|
||||
// on retry
|
||||
(exception, timeSpan, retryCount, context) =>
|
||||
{
|
||||
var msg = $"Retry {retryCount} implemented with Polly's RetryPolicy " +
|
||||
$"of {context.PolicyKey} " +
|
||||
$"at {context.OperationKey}, " +
|
||||
$"due to: {exception}.";
|
||||
_logger.LogWarning(msg);
|
||||
_logger.LogDebug(msg);
|
||||
});
|
||||
}
|
||||
|
||||
public Policy GetCircuitBreakerPolicy()
|
||||
{
|
||||
return Policy.Handle<HttpRequestException>()
|
||||
.CircuitBreakerAsync(
|
||||
// number of exceptions before breaking circuit
|
||||
EXCEPTIONS_ALLOWED_BEFORE_CIRCUIT_BREAKER,
|
||||
// time circuit opened before retry
|
||||
TimeSpan.FromMinutes(1),
|
||||
(exception, duration) =>
|
||||
{
|
||||
// on circuit opened
|
||||
_logger.LogTrace("Circuit breaker opened");
|
||||
},
|
||||
() =>
|
||||
{
|
||||
// on circuit closed
|
||||
_logger.LogTrace("Circuit breaker reset");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http;
|
||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||
using Microsoft.eShopOnContainers.WebMVC.ViewModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WebMVC.Infrastructure;
|
||||
using WebMVC.Models;
|
||||
@ -15,29 +13,26 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
public class BasketService : IBasketService
|
||||
{
|
||||
private readonly IOptionsSnapshot<AppSettings> _settings;
|
||||
private readonly IHttpClient _apiClient;
|
||||
private readonly HttpClient _apiClient;
|
||||
private readonly string _basketByPassUrl;
|
||||
private readonly string _purchaseUrl;
|
||||
private readonly IHttpContextAccessor _httpContextAccesor;
|
||||
|
||||
private readonly string _bffUrl;
|
||||
|
||||
public BasketService(IOptionsSnapshot<AppSettings> settings,
|
||||
IHttpContextAccessor httpContextAccesor, IHttpClient httpClient)
|
||||
public BasketService(HttpClient httpClient,IOptionsSnapshot<AppSettings> settings)
|
||||
{
|
||||
_apiClient = httpClient;
|
||||
_settings = settings;
|
||||
|
||||
_basketByPassUrl = $"{_settings.Value.PurchaseUrl}/api/v1/b/basket";
|
||||
_purchaseUrl = $"{_settings.Value.PurchaseUrl}/api/v1";
|
||||
_httpContextAccesor = httpContextAccesor;
|
||||
_apiClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task<Basket> GetBasket(ApplicationUser user)
|
||||
{
|
||||
var token = await GetUserTokenAsync();
|
||||
var getBasketUri = API.Basket.GetBasket(_basketByPassUrl, user.Id);
|
||||
|
||||
var dataString = await _apiClient.GetStringAsync(getBasketUri, token);
|
||||
var dataString = await _apiClient.GetStringAsync(getBasketUri);
|
||||
|
||||
return string.IsNullOrEmpty(dataString) ?
|
||||
new Basket() { BuyerId = user.Id} :
|
||||
@ -46,10 +41,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
public async Task<Basket> UpdateBasket(Basket basket)
|
||||
{
|
||||
var token = await GetUserTokenAsync();
|
||||
var updateBasketUri = API.Basket.UpdateBasket(_basketByPassUrl);
|
||||
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
@ -58,10 +53,10 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
public async Task Checkout(BasketDTO basket)
|
||||
{
|
||||
var token = await GetUserTokenAsync();
|
||||
var updateBasketUri = API.Basket.CheckoutBasket(_basketByPassUrl);
|
||||
var content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, basket, token);
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
@ -69,54 +64,52 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
public async Task<Basket> SetQuantities(ApplicationUser user, Dictionary<string, int> quantities)
|
||||
{
|
||||
|
||||
var token = await GetUserTokenAsync();
|
||||
var updateBasketUri = API.Purchase.UpdateBasketItem(_purchaseUrl);
|
||||
var userId = user.Id;
|
||||
|
||||
var response = await _apiClient.PutAsync(updateBasketUri, new
|
||||
var basketUpdate = new
|
||||
{
|
||||
BasketId = userId,
|
||||
BasketId = user.Id,
|
||||
Updates = quantities.Select(kvp => new
|
||||
{
|
||||
BasketItemId = kvp.Key,
|
||||
NewQty = kvp.Value
|
||||
}).ToArray()
|
||||
}, token);
|
||||
};
|
||||
|
||||
var content = new StringContent(JsonConvert.SerializeObject(basketUpdate), System.Text.Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _apiClient.PutAsync(updateBasketUri,content);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||
|
||||
return JsonConvert.DeserializeObject<Basket>(jsonResponse);
|
||||
}
|
||||
|
||||
public async Task<Order> GetOrderDraft(string basketId)
|
||||
{
|
||||
var token = await GetUserTokenAsync();
|
||||
var draftOrderUri = API.Purchase.GetOrderDraft(_purchaseUrl, basketId);
|
||||
var json = await _apiClient.GetStringAsync(draftOrderUri, token);
|
||||
return JsonConvert.DeserializeObject<Order>(json);
|
||||
var response = await _apiClient.GetStringAsync(draftOrderUri);
|
||||
|
||||
return JsonConvert.DeserializeObject<Order>(response);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task AddItemToBasket(ApplicationUser user, int productId)
|
||||
{
|
||||
var token = await GetUserTokenAsync();
|
||||
var updateBasketUri = API.Purchase.AddItemToBasket(_purchaseUrl);
|
||||
var userId = user.Id;
|
||||
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, new
|
||||
var newItem = new
|
||||
{
|
||||
CatalogItemId = productId,
|
||||
BasketId = userId,
|
||||
BasketId = user.Id,
|
||||
Quantity = 1
|
||||
}, token);
|
||||
};
|
||||
|
||||
}
|
||||
var content = new StringContent(JsonConvert.SerializeObject(newItem), System.Text.Encoding.UTF8, "application/json");
|
||||
|
||||
async Task<string> GetUserTokenAsync()
|
||||
{
|
||||
var context = _httpContextAccesor.HttpContext;
|
||||
return await context.GetTokenAsync("access_token");
|
||||
var response = await _apiClient.PostAsync(updateBasketUri, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,9 +14,12 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.HealthChecks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Polly;
|
||||
using Polly.Registry;
|
||||
using StackExchange.Redis;
|
||||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http;
|
||||
using WebMVC.Infrastructure;
|
||||
using WebMVC.Infrastructure.Middlewares;
|
||||
using WebMVC.Services;
|
||||
@ -35,104 +38,11 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
RegisterAppInsights(services);
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
services.AddSession();
|
||||
|
||||
if (Configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||
{
|
||||
services.AddDataProtection(opts =>
|
||||
{
|
||||
opts.ApplicationDiscriminator = "eshop.webmvc";
|
||||
})
|
||||
.PersistKeysToRedis(ConnectionMultiplexer.Connect(Configuration["DPConnectionString"]), "DataProtection-Keys");
|
||||
}
|
||||
|
||||
services.Configure<AppSettings>(Configuration);
|
||||
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(Configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
|
||||
checks.AddUrlCheck(Configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheck(Configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(Configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
|
||||
// Add application services.
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
services.AddTransient<ICatalogService, CatalogService>();
|
||||
services.AddTransient<IOrderingService, OrderingService>();
|
||||
services.AddTransient<IBasketService, BasketService>();
|
||||
services.AddTransient<ICampaignService, CampaignService>();
|
||||
services.AddTransient<ILocationService, LocationService>();
|
||||
services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
|
||||
|
||||
if (Configuration.GetValue<string>("UseResilientHttp") == bool.TrueString)
|
||||
{
|
||||
services.AddSingleton<IResilientHttpClientFactory, ResilientHttpClientFactory>(sp =>
|
||||
{
|
||||
var logger = sp.GetRequiredService<ILogger<ResilientHttpClient>>();
|
||||
var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>();
|
||||
|
||||
var retryCount = 6;
|
||||
if (!string.IsNullOrEmpty(Configuration["HttpClientRetryCount"]))
|
||||
{
|
||||
retryCount = int.Parse(Configuration["HttpClientRetryCount"]);
|
||||
}
|
||||
|
||||
var exceptionsAllowedBeforeBreaking = 5;
|
||||
if (!string.IsNullOrEmpty(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]))
|
||||
{
|
||||
exceptionsAllowedBeforeBreaking = int.Parse(Configuration["HttpClientExceptionsAllowedBeforeBreaking"]);
|
||||
}
|
||||
|
||||
return new ResilientHttpClientFactory(logger, httpContextAccessor, exceptionsAllowedBeforeBreaking, retryCount);
|
||||
});
|
||||
services.AddSingleton<IHttpClient, ResilientHttpClient>(sp => sp.GetService<IResilientHttpClientFactory>().CreateResilientHttpClient());
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<IHttpClient, StandardHttpClient>();
|
||||
}
|
||||
var useLoadTest = Configuration.GetValue<bool>("UseLoadTest");
|
||||
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
||||
var callBackUrl = Configuration.GetValue<string>("CallBackUrl");
|
||||
|
||||
// Add Authentication services
|
||||
|
||||
services.AddAuthentication(options => {
|
||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie()
|
||||
.AddOpenIdConnect(options => {
|
||||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.Authority = identityUrl.ToString();
|
||||
options.SignedOutRedirectUri = callBackUrl.ToString();
|
||||
options.ClientId = useLoadTest ? "mvctest" : "mvc";
|
||||
options.ClientSecret = "secret";
|
||||
options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
|
||||
options.SaveTokens = true;
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
options.RequireHttpsMetadata = false;
|
||||
options.Scope.Add("openid");
|
||||
options.Scope.Add("profile");
|
||||
options.Scope.Add("orders");
|
||||
options.Scope.Add("basket");
|
||||
options.Scope.Add("marketing");
|
||||
options.Scope.Add("locations");
|
||||
options.Scope.Add("webshoppingagg");
|
||||
options.Scope.Add("orders.signalrhub");
|
||||
});
|
||||
services.AddAppInsight(Configuration)
|
||||
.AddHealthChecks(Configuration)
|
||||
.AddCustomMvc(Configuration)
|
||||
.AddCustomApplicationServices(Configuration)
|
||||
.AddCustomAuthentication(Configuration);
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
@ -140,8 +50,6 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
{
|
||||
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
||||
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
loggerFactory.AddAzureWebAppDiagnostics();
|
||||
loggerFactory.AddApplicationInsights(app.ApplicationServices, LogLevel.Trace);
|
||||
|
||||
@ -173,7 +81,7 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
{
|
||||
app.UseMiddleware<ByPassAuthMiddleware>();
|
||||
}
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
var log = loggerFactory.CreateLogger("identity");
|
||||
@ -191,23 +99,162 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
template: "{controller=Error}/{action=Error}");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterAppInsights(IServiceCollection services)
|
||||
static class ServiceCollectionExtensions
|
||||
{
|
||||
|
||||
public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddApplicationInsightsTelemetry(Configuration);
|
||||
var orchestratorType = Configuration.GetValue<string>("OrchestratorType");
|
||||
services.AddApplicationInsightsTelemetry(configuration);
|
||||
var orchestratorType = configuration.GetValue<string>("OrchestratorType");
|
||||
|
||||
if (orchestratorType?.ToUpper() == "K8S")
|
||||
{
|
||||
// Enable K8s telemetry initializer
|
||||
services.EnableKubernetes();
|
||||
}
|
||||
|
||||
if (orchestratorType?.ToUpper() == "SF")
|
||||
{
|
||||
// Enable SF telemetry initializer
|
||||
services.AddSingleton<ITelemetryInitializer>((serviceProvider) =>
|
||||
new FabricTelemetryInitializer());
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddHealthChecks(checks =>
|
||||
{
|
||||
var minutes = 1;
|
||||
if (int.TryParse(configuration["HealthCheck:Timeout"], out var minutesParsed))
|
||||
{
|
||||
minutes = minutesParsed;
|
||||
}
|
||||
|
||||
checks.AddUrlCheck(configuration["CatalogUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["OrderingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["BasketUrlHC"], TimeSpan.Zero); //No cache for this HealthCheck, better just for demos
|
||||
checks.AddUrlCheck(configuration["IdentityUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
checks.AddUrlCheck(configuration["MarketingUrlHC"], TimeSpan.FromMinutes(minutes));
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddMvc();
|
||||
|
||||
services.AddSession();
|
||||
|
||||
if (configuration.GetValue<string>("IsClusterEnv") == bool.TrueString)
|
||||
{
|
||||
services.AddDataProtection(opts =>
|
||||
{
|
||||
opts.ApplicationDiscriminator = "eshop.webmvc";
|
||||
})
|
||||
.PersistKeysToRedis(ConnectionMultiplexer.Connect(configuration["DPConnectionString"]), "DataProtection-Keys");
|
||||
}
|
||||
|
||||
services.Configure<AppSettings>(configuration);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddCustomApplicationServices(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
services.AddSingleton<HttpClientDefaultPolicies>();
|
||||
var defaultPolicies = services.BuildServiceProvider().GetService<HttpClientDefaultPolicies>();
|
||||
|
||||
var registry = services.AddPolicyRegistry();
|
||||
registry.Add("WaitAndRetry", defaultPolicies.GetWaitAndRetryPolicy());
|
||||
registry.Add("CircuitBreaker", defaultPolicies.GetCircuitBreakerPolicy());
|
||||
|
||||
services.AddHttpClient<IBasketService, BasketService>()
|
||||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
||||
.AddPolicyHandlerFromRegistry("WaitAndRetry")
|
||||
.AddPolicyHandlerFromRegistry("CircuitBreaker");
|
||||
|
||||
services.AddTransient<ICatalogService, CatalogService>();
|
||||
services.AddTransient<IOrderingService, OrderingService>();
|
||||
|
||||
services.AddTransient<ICampaignService, CampaignService>();
|
||||
services.AddTransient<ILocationService, LocationService>();
|
||||
services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
|
||||
|
||||
if (configuration.GetValue<string>("UseResilientHttp") == bool.TrueString)
|
||||
{
|
||||
services.AddSingleton<IResilientHttpClientFactory, ResilientHttpClientFactory>(sp =>
|
||||
{
|
||||
var logger = sp.GetRequiredService<ILogger<ResilientHttpClient>>();
|
||||
var httpContextAccessor = sp.GetRequiredService<IHttpContextAccessor>();
|
||||
|
||||
var retryCount = 6;
|
||||
if (!string.IsNullOrEmpty(configuration["HttpClientRetryCount"]))
|
||||
{
|
||||
retryCount = int.Parse(configuration["HttpClientRetryCount"]);
|
||||
}
|
||||
|
||||
var exceptionsAllowedBeforeBreaking = 5;
|
||||
if (!string.IsNullOrEmpty(configuration["HttpClientExceptionsAllowedBeforeBreaking"]))
|
||||
{
|
||||
exceptionsAllowedBeforeBreaking = int.Parse(configuration["HttpClientExceptionsAllowedBeforeBreaking"]);
|
||||
}
|
||||
|
||||
return new ResilientHttpClientFactory(logger, httpContextAccessor, exceptionsAllowedBeforeBreaking, retryCount);
|
||||
});
|
||||
services.AddSingleton<IHttpClient, ResilientHttpClient>(sp => sp.GetService<IResilientHttpClientFactory>().CreateResilientHttpClient());
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<IHttpClient, StandardHttpClient>();
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var useLoadTest = configuration.GetValue<bool>("UseLoadTest");
|
||||
var identityUrl = configuration.GetValue<string>("IdentityUrl");
|
||||
var callBackUrl = configuration.GetValue<string>("CallBackUrl");
|
||||
|
||||
// Add Authentication services
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddCookie()
|
||||
.AddOpenIdConnect(options =>
|
||||
{
|
||||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.Authority = identityUrl.ToString();
|
||||
options.SignedOutRedirectUri = callBackUrl.ToString();
|
||||
options.ClientId = useLoadTest ? "mvctest" : "mvc";
|
||||
options.ClientSecret = "secret";
|
||||
options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
|
||||
options.SaveTokens = true;
|
||||
options.GetClaimsFromUserInfoEndpoint = true;
|
||||
options.RequireHttpsMetadata = false;
|
||||
options.Scope.Add("openid");
|
||||
options.Scope.Add("profile");
|
||||
options.Scope.Add("orders");
|
||||
options.Scope.Add("basket");
|
||||
options.Scope.Add("marketing");
|
||||
options.Scope.Add("locations");
|
||||
options.Scope.Add("webshoppingagg");
|
||||
options.Scope.Add("orders.signalrhub");
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="2.6.1" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.0.0-beta8" />
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.ServiceFabric" Version="2.1.1-beta1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0-rc1-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="2.1.0-rc1-final" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0-rc1-final" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Redis" Version="0.3.3" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user