From 041323bad5bea5b51fc4cfa102eb965d5d2fca4f Mon Sep 17 00:00:00 2001 From: mark-robustelli <137117976+mark-robustelli@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:31:57 -0700 Subject: [PATCH 1/4] exposing client builder to allow httpClient. --- .../src/io/fusionauth/DefaultRESTClient.cs | 22 ++++++++++++++++--- .../src/io/fusionauth/FusionAuthClient.cs | 20 +++++++++++++++++ .../src/io/fusionauth/FusionAuthSyncClient.cs | 11 ++++++++-- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs index 21e76ff3..ce73f34d 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs @@ -19,6 +19,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using com.inversoft.error; @@ -28,7 +29,7 @@ using Newtonsoft.Json.Serialization; namespace io.fusionauth { - class DefaultRESTClient : IRESTClient { + public class DefaultRESTClient : IRESTClient { public HttpClient httpClient; public HttpContent content; @@ -57,6 +58,10 @@ public DefaultRESTClient(string host) { httpClient = new HttpClient {BaseAddress = new Uri(host)}; } + public DefaultRESTClient(HttpClient incomingHttpClient) { + httpClient = incomingHttpClient; + } + /** * Sets the authorization header using a key * @@ -169,7 +174,18 @@ private Task baseRequest() { // - Bypass this additional validation for the Authorization header. If we find other edge cases, perhaps // we should just always use TryAddWithoutValidation unless there is a security risk. if (key == "Authorization") { - httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); + if (httpClient.DefaultRequestHeaders.Authorization == null) + { + httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); + } + else + { + if (httpClient.DefaultRequestHeaders.Authorization.ToString() != value) + { + httpClient.DefaultRequestHeaders.Clear(); + httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); + } + } } else { httpClient.DefaultRequestHeaders.Add(key, value); } @@ -228,4 +244,4 @@ public override Task> goAsync() { }); } } -} \ No newline at end of file +} diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs index 561f01c1..e2d4e106 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthClient.cs @@ -3300,4 +3300,24 @@ public IRESTClient build(string host) { return new DefaultRESTClient(host); } } + + public class HttpClientBuilder : IRESTClientBuilder + { + public HttpClient HTTP_CLIENT; + + public HttpClientBuilder(HttpClient httpClient) + { + HTTP_CLIENT = httpClient; + } + + public IRESTClient build(string host) + { + if (HTTP_CLIENT.BaseAddress == null) + { + HTTP_CLIENT.BaseAddress = new Uri(host); + } + return new DefaultRESTClient(HTTP_CLIENT); + } + + } } diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs index 9b4a16e8..f5a3188f 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs @@ -33,8 +33,15 @@ namespace io.fusionauth { public class FusionAuthSyncClient : IFusionAuthSyncClient { public readonly FusionAuthClient client; - public FusionAuthSyncClient(string apiKey, string host, string tenantId = null) { - client = new FusionAuthClient(apiKey, host, tenantId); + public FusionAuthSyncClient(string apiKey, string host, string tenantId = null, IRESTClientBuilder clientBuilder = null) { + if (clientBuilder == null) + { + client = new FusionAuthClient(apiKey, host, tenantId); + } + else + { + client = new FusionAuthClient(apiKey, host, tenantId, clientBuilder); + } } /** From fa3f9e67e66f6ec4cb76559c67863dda1dd800aa Mon Sep 17 00:00:00 2001 From: Mark Robustelli <137117976+mark-robustelli@users.noreply.github.com> Date: Wed, 28 Feb 2024 11:18:23 -0700 Subject: [PATCH 2/4] Update FusionAuthSyncClient.cs syncing with changes to fusionauth-client-builder FusionAuthSyncClient. --- .../src/io/fusionauth/FusionAuthSyncClient.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs index f5a3188f..9437c50d 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/FusionAuthSyncClient.cs @@ -34,14 +34,7 @@ public class FusionAuthSyncClient : IFusionAuthSyncClient { public readonly FusionAuthClient client; public FusionAuthSyncClient(string apiKey, string host, string tenantId = null, IRESTClientBuilder clientBuilder = null) { - if (clientBuilder == null) - { - client = new FusionAuthClient(apiKey, host, tenantId); - } - else - { - client = new FusionAuthClient(apiKey, host, tenantId, clientBuilder); - } + client = new FusionAuthClient(apiKey, host, tenantId, clientBuilder); } /** From ee5cf8e2a9194e463ada85463b3a8623119f3deb Mon Sep 17 00:00:00 2001 From: Mark Robustelli <137117976+mark-robustelli@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:19:26 -0700 Subject: [PATCH 3/4] Update DefaultRESTClient.cs Making cleaner. Since the baseRequest function expected a clean httpClient every call, I just added a clear to the headers instead of all the validation logic. --- .../src/io/fusionauth/DefaultRESTClient.cs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs index ce73f34d..0db19d48 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs @@ -169,23 +169,13 @@ private string getFullUri() { } private Task baseRequest() { + httpClient.Default.RequestHeaders.Clear(); foreach (var (key, value) in headers.Select(x => (x.Key, x.Value))) { // .Add performs additional validation on the 'value' that may fail if an API key contains a '=' character. // - Bypass this additional validation for the Authorization header. If we find other edge cases, perhaps // we should just always use TryAddWithoutValidation unless there is a security risk. if (key == "Authorization") { - if (httpClient.DefaultRequestHeaders.Authorization == null) - { - httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); - } - else - { - if (httpClient.DefaultRequestHeaders.Authorization.ToString() != value) - { - httpClient.DefaultRequestHeaders.Clear(); - httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); - } - } + httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value); } else { httpClient.DefaultRequestHeaders.Add(key, value); } From 2bfb71232826d812bbe95f2494f741c5d282aa48 Mon Sep 17 00:00:00 2001 From: Mark Robustelli <137117976+mark-robustelli@users.noreply.github.com> Date: Wed, 28 Feb 2024 12:22:58 -0700 Subject: [PATCH 4/4] Update DefaultRESTClient.cs typo --- .../src/io/fusionauth/DefaultRESTClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs index 0db19d48..9ef1b107 100644 --- a/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs +++ b/fusionauth-netcore-client/src/io/fusionauth/DefaultRESTClient.cs @@ -169,7 +169,7 @@ private string getFullUri() { } private Task baseRequest() { - httpClient.Default.RequestHeaders.Clear(); + httpClient.DefaultRequestHeaders.Clear(); foreach (var (key, value) in headers.Select(x => (x.Key, x.Value))) { // .Add performs additional validation on the 'value' that may fail if an API key contains a '=' character. // - Bypass this additional validation for the Authorization header. If we find other edge cases, perhaps