From aecb81aefa1e5b37e5fd0d3e5bf97ec96f6dc74b Mon Sep 17 00:00:00 2001 From: Eduard Tomas Date: Mon, 8 May 2017 16:07:51 +0200 Subject: [PATCH] Fixed error on sharing policies between origins --- .../Resilience.Http/ResilientHttpClient.cs | 48 ++++++++++++++----- .../ResilientHttpClientFactory.cs | 2 +- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs index 88aef22aa..a76e60f0b 100644 --- a/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs +++ b/src/BuildingBlocks/Resilience/Resilience.Http/ResilientHttpClient.cs @@ -3,6 +3,8 @@ using Newtonsoft.Json; using Polly; using Polly.Wrap; using System; +using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -18,29 +20,45 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http public class ResilientHttpClient : IHttpClient { private HttpClient _client; - private PolicyWrap _policyWrapper; + private readonly Dictionary _policiesPerOrigin; private ILogger _logger; + private readonly Func> _policyCreator; //public HttpClient Inst => _client; - public ResilientHttpClient(Policy[] policies, ILogger logger) + public ResilientHttpClient(Func> policyCreator, ILogger logger) { _client = new HttpClient(); _logger = logger; - - // Add Policies to be applied - _policyWrapper = Policy.WrapAsync(policies); + _policiesPerOrigin = new Dictionary(); + _policyCreator = policyCreator; } - private Task HttpInvoker(Func> action) + private Task HttpInvoker(string origin, Func> action) { + var normalizedOrigin = NormalizeOrigin(origin); + + if (!_policiesPerOrigin.ContainsKey(normalizedOrigin)) + { + var newWrapper = Policy.WrapAsync(_policyCreator(normalizedOrigin).ToArray()); + _policiesPerOrigin.Add(normalizedOrigin, newWrapper); + } + + var policyWrapper = _policiesPerOrigin[normalizedOrigin]; + // Executes the action applying all // the policies defined in the wrapper - return _policyWrapper.ExecuteAsync(() => action()); + return policyWrapper.ExecuteAsync(() => action()); + } + + private static string NormalizeOrigin(string origin) + { + return origin?.Trim()?.ToLower(); } public Task GetStringAsync(string uri, string authorizationToken = null, string authorizationMethod = "Bearer") { - return HttpInvoker(async () => + var origin = GetOriginFromUri(uri); + return HttpInvoker(origin, async () => { var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); @@ -55,9 +73,15 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http }); } - private Task DoPostPutAsync(HttpMethod method, string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") + private static string GetOriginFromUri(string uri) { + var url = new Uri(uri); + var origin = $"{url.Scheme}://{url.DnsSafeHost}:{url.Port}"; + return origin; + } + private Task DoPostPutAsync(HttpMethod method, string uri, T item, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") + { if (method != HttpMethod.Post && method != HttpMethod.Put) { throw new ArgumentException("Value must be either post or put.", nameof(method)); @@ -65,7 +89,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http // a new StringContent must be created for each retry // as it is disposed after each call - return HttpInvoker(async () => + var origin = GetOriginFromUri(uri); + return HttpInvoker(origin, async () => { var requestMessage = new HttpRequestMessage(method, uri); @@ -105,7 +130,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.Resilience.Http } public Task DeleteAsync(string uri, string authorizationToken = null, string requestId = null, string authorizationMethod = "Bearer") { - return HttpInvoker(async () => + var origin = GetOriginFromUri(uri); + return HttpInvoker(origin, async () => { var requestMessage = new HttpRequestMessage(HttpMethod.Delete, uri); diff --git a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs b/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs index 8efadf366..8eb43179d 100644 --- a/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs +++ b/src/Web/WebMVC/Infrastructure/ResilientHttpClientFactory.cs @@ -17,7 +17,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.Infrastructure =>_logger = logger; public ResilientHttpClient CreateResilientHttpClient() - => new ResilientHttpClient(CreatePolicies(), _logger); + => new ResilientHttpClient((origin) => CreatePolicies(), _logger); private Policy[] CreatePolicies()