From e2e1acf9a124380b9d05c9be7fd068a66d552fee Mon Sep 17 00:00:00 2001 From: Mujahid Daud Khan Date: Mon, 27 May 2024 18:18:06 +0500 Subject: [PATCH 1/2] feat: add auto refresh token support --- APIMatic.Core/APIMatic.Core.csproj | 1 + APIMatic.Core/ApiCall.cs | 2 +- APIMatic.Core/Authentication/AuthGroupBuilder.cs | 8 ++++++-- APIMatic.Core/Authentication/AuthManager.cs | 4 +++- APIMatic.Core/Request/RequestBuilder.cs | 5 +++-- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/APIMatic.Core/APIMatic.Core.csproj b/APIMatic.Core/APIMatic.Core.csproj index 074173b0..b4f12e29 100644 --- a/APIMatic.Core/APIMatic.Core.csproj +++ b/APIMatic.Core/APIMatic.Core.csproj @@ -20,6 +20,7 @@ APIMatic;dotnet;core;Core Library https://www.apimatic.io icon.png + 5d4cfd39-614d-4884-b9bc-d138d7d3d778 diff --git a/APIMatic.Core/ApiCall.cs b/APIMatic.Core/ApiCall.cs index f9300265..aaf71b43 100644 --- a/APIMatic.Core/ApiCall.cs +++ b/APIMatic.Core/ApiCall.cs @@ -102,7 +102,7 @@ public ApiCall ExecuteAsync(CancellationToken cancellationToken = default) { requestBuilder.AcceptHeader = responseHandler.AcceptHeader; - CoreRequest request = requestBuilder.Build(); + CoreRequest request = await requestBuilder.Build(); globalConfiguration.ApiCallback?.OnBeforeHttpRequestEventHandler(request); _sdkLogger.LogRequest(request); CoreResponse response = await globalConfiguration.HttpClient.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); diff --git a/APIMatic.Core/Authentication/AuthGroupBuilder.cs b/APIMatic.Core/Authentication/AuthGroupBuilder.cs index 99f3acb8..5a84e668 100644 --- a/APIMatic.Core/Authentication/AuthGroupBuilder.cs +++ b/APIMatic.Core/Authentication/AuthGroupBuilder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using APIMatic.Core.Request; using APIMatic.Core.Types.Sdk.Exceptions; @@ -112,10 +113,13 @@ public override void Validate() /// Add authentication group information to the RequestBuilder. /// /// The RequestBuilder object on which authentication will be applied. - internal override void Apply(RequestBuilder requestBuilder) + public override async Task Apply(RequestBuilder requestBuilder) { Validate(); - validatedAuthManagers.ForEach(authManager => authManager.Apply(requestBuilder)); + foreach (var authManager in validatedAuthManagers) + { + await authManager.Apply(requestBuilder); + } } } } diff --git a/APIMatic.Core/Authentication/AuthManager.cs b/APIMatic.Core/Authentication/AuthManager.cs index c9db2e66..7345bdbf 100644 --- a/APIMatic.Core/Authentication/AuthManager.cs +++ b/APIMatic.Core/Authentication/AuthManager.cs @@ -2,6 +2,7 @@ // Copyright (c) APIMatic. All rights reserved. // using System; +using System.Threading.Tasks; using APIMatic.Core.Request; using APIMatic.Core.Request.Parameters; @@ -37,10 +38,11 @@ public virtual void Validate() /// Add authentication information to the HTTP Request. /// /// The http request object on which authentication will be applied. - internal virtual void Apply(RequestBuilder requestBuilder) + public virtual Task Apply(RequestBuilder requestBuilder) { Validate(); parameters.Apply(requestBuilder); + return Task.CompletedTask; } } } diff --git a/APIMatic.Core/Request/RequestBuilder.cs b/APIMatic.Core/Request/RequestBuilder.cs index d8c1a853..3e991b0c 100644 --- a/APIMatic.Core/Request/RequestBuilder.cs +++ b/APIMatic.Core/Request/RequestBuilder.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Text; +using System.Threading.Tasks; using APIMatic.Core.Authentication; using APIMatic.Core.Http.Configuration; using APIMatic.Core.Request.Parameters; @@ -145,11 +146,11 @@ public RequestBuilder XmlBodySerializer(Func xmlSerializer) /// This applies all the configuration and build an instance of CoreRequest /// /// - public CoreRequest Build() + public async Task Build() { parameters.Validate().Apply(this); configuration.RuntimeParameters.Validate().Apply(this); - authGroup.Apply(this); + await authGroup.Apply(this); CoreHelper.AppendUrlWithQueryParameters(QueryUrl, queryParameters, ArraySerialization); body = bodyParameters.Any() ? bodyParameters : body; AppendContentTypeHeader(); From d047f1da63dc0fad3afcd9d509f93e77d50d6da6 Mon Sep 17 00:00:00 2001 From: Mujahid Daud Khan Date: Fri, 31 May 2024 16:56:43 +0500 Subject: [PATCH 2/2] feat: update unit tests with auto refresh code --- APIMatic.Core.Test/AuthenticationTest.cs | 32 ++++++++++++------- APIMatic.Core.Test/GlobalConfigurationTest.cs | 15 +++++---- .../Http/HttpClientWrapperSSLTest.cs | 28 ++++++++-------- .../Http/HttpClientWrapperTest.cs | 6 ++-- APIMatic.Core/APIMatic.Core.csproj | 1 - 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/APIMatic.Core.Test/AuthenticationTest.cs b/APIMatic.Core.Test/AuthenticationTest.cs index fd801f96..46ffde7a 100644 --- a/APIMatic.Core.Test/AuthenticationTest.cs +++ b/APIMatic.Core.Test/AuthenticationTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Net.Http; +using System.Threading.Tasks; using APIMatic.Core.Authentication; using APIMatic.Core.Test.MockTypes.Authentication; using APIMatic.Core.Types.Sdk.Exceptions; @@ -12,7 +13,7 @@ namespace APIMatic.Core.Test public class AuthenticationTest : TestBase { [Test] - public void Multiple_Authentication_Success_WithFirstAuth() + public async Task Multiple_Authentication_Success_WithFirstAuth() { var globalConfiguration = new GlobalConfiguration.Builder() .ServerUrls(new Dictionary @@ -28,7 +29,7 @@ public void Multiple_Authentication_Success_WithFirstAuth() .HttpConfiguration(_clientConfiguration) .Build(); - var request = globalConfiguration.GlobalRequestBuilder() + var request = await globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") .WithOrAuth(auth => auth .AddAndGroup(innerGroup => innerGroup @@ -45,7 +46,7 @@ public void Multiple_Authentication_Success_WithFirstAuth() } [Test] - public void Multiple_Authentication_Success_WithSecondAuth() + public async Task Multiple_Authentication_Success_WithSecondAuth() { var basicAuthManager = new BasicAuthManager("username", "password"); var globalConfiguration = new GlobalConfiguration.Builder() @@ -62,7 +63,7 @@ public void Multiple_Authentication_Success_WithSecondAuth() .HttpConfiguration(_clientConfiguration) .Build(); - var request = globalConfiguration.GlobalRequestBuilder() + var request = await globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") .WithOrAuth(auth => auth .AddAndGroup(innerGroup => innerGroup @@ -95,7 +96,7 @@ public void Multiple_Authentication_OR_Validation_Failure() .HttpConfiguration(_clientConfiguration) .Build(); - var exp = Assert.Throws(() => globalConfiguration.GlobalRequestBuilder() + var exp = Assert.ThrowsAsync(() => globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") .WithOrAuth(auth => auth .Add("basic") @@ -110,7 +111,7 @@ public void Multiple_Authentication_OR_Validation_Failure() } [Test] - public void Multiple_Authentication_AND_Validation_Failure() + public async Task Multiple_Authentication_AND_Validation_Failure() { var globalConfiguration = new GlobalConfiguration.Builder() .ServerUrls(new Dictionary @@ -126,15 +127,24 @@ public void Multiple_Authentication_AND_Validation_Failure() .HttpConfiguration(_clientConfiguration) .Build(); - var exp = Assert.Throws(() => globalConfiguration.GlobalRequestBuilder() + + var exp = Assert.ThrowsAsync(() => globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") - .WithAndAuth(auth => auth - .Add("query") + .WithAndAuth(auth => auth.Add("query") .Add("header")) .Build()); Assert.AreEqual("Following authentication credentials are required:\n" + "-> Missing required header field: TOKEN", exp.Message); + + async void AuthCode() + { + await globalConfiguration.GlobalRequestBuilder() + .Setup(HttpMethod.Get, "/auth") + .WithAndAuth(auth => auth.Add("query") + .Add("header")) + .Build(); + } } [Test] @@ -153,7 +163,7 @@ public void Multiple_Authentication_AND_All_Missing_Validation_Failure() .HttpConfiguration(_clientConfiguration) .Build(); - var exp = Assert.Throws(() => globalConfiguration.GlobalRequestBuilder() + var exp = Assert.ThrowsAsync(() => globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") .WithAndAuth(auth => auth .Add("query") @@ -184,7 +194,7 @@ public void Multiple_Authentication_AND_with_nested_OR_Validation_Failure() .HttpConfiguration(_clientConfiguration) .Build(); - var exp = Assert.Throws(() => globalConfiguration.GlobalRequestBuilder() + var exp = Assert.ThrowsAsync(() => globalConfiguration.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/auth") .WithAndAuth(auth => auth .Add("query") diff --git a/APIMatic.Core.Test/GlobalConfigurationTest.cs b/APIMatic.Core.Test/GlobalConfigurationTest.cs index c421d0a5..853bc70c 100644 --- a/APIMatic.Core.Test/GlobalConfigurationTest.cs +++ b/APIMatic.Core.Test/GlobalConfigurationTest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Threading.Tasks; using APIMatic.Core.Http.Configuration; using NUnit.Framework; @@ -19,19 +20,19 @@ public void TestServerUrl() } [Test] - public void TestGlobalRequestQueryUrl() + public async Task TestGlobalRequestQueryUrl() { - var request = LazyGlobalConfiguration.Value.GlobalRequestBuilder().Build(); + var request = await LazyGlobalConfiguration.Value.GlobalRequestBuilder().Build(); Assert.AreEqual("http://my/path:3000/v1", request.QueryUrl); - var request2 = LazyGlobalConfiguration.Value.GlobalRequestBuilder(MockServer.Server2).Build(); + var request2 = await LazyGlobalConfiguration.Value.GlobalRequestBuilder(MockServer.Server2).Build(); Assert.AreEqual("https://my/path/v2", request2.QueryUrl); } [Test] - public void TestGlobalRequestHeaders() + public async Task TestGlobalRequestHeaders() { - var request = LazyGlobalConfiguration.Value.GlobalRequestBuilder().Build(); + var request = await LazyGlobalConfiguration.Value.GlobalRequestBuilder().Build(); Assert.True(request.Headers.Count == 5); Assert.AreEqual("headVal1", request.Headers["additionalHead1"]); Assert.AreEqual("headVal2", request.Headers["additionalHead2"]); @@ -41,10 +42,10 @@ public void TestGlobalRequestHeaders() } [Test] - public void TestGlobalRequest_NullUserAgent() + public async Task TestGlobalRequest_NullUserAgent() { var httpClientConfiguration = new CoreHttpClientConfiguration.Builder().Build(); - var request = new GlobalConfiguration.Builder() + var request = await new GlobalConfiguration.Builder() .HttpConfiguration(httpClientConfiguration) .UserAgent(null) .ServerUrls(new Dictionary diff --git a/APIMatic.Core.Test/Http/HttpClientWrapperSSLTest.cs b/APIMatic.Core.Test/Http/HttpClientWrapperSSLTest.cs index 6800a6d5..33917251 100644 --- a/APIMatic.Core.Test/Http/HttpClientWrapperSSLTest.cs +++ b/APIMatic.Core.Test/Http/HttpClientWrapperSSLTest.cs @@ -3,7 +3,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; -using APIMatic.Core.Http.Configuration; +using APIMatic.Core.Http.Configuration; using NUnit.Framework; namespace APIMatic.Core.Test.Http @@ -11,13 +11,13 @@ namespace APIMatic.Core.Test.Http [TestFixture] public class HttpClientWrapperSSLTest : TestBase { - private readonly string expiredSSLCertUrl = "https://expired.badssl.com/"; - + private readonly string expiredSSLCertUrl = "https://expired.badssl.com/"; + [Test] - public void TestHttpClientSSLCertificateVerification_ExceptionResponse() - { - var expectedValue = "The SSL connection could not be established, see inner exception."; - var clientConfiguration = new CoreHttpClientConfiguration.Builder() + public async Task TestHttpClientSSLCertificateVerification_ExceptionResponse() + { + var expectedValue = "The SSL connection could not be established, see inner exception."; + var clientConfiguration = new CoreHttpClientConfiguration.Builder() .Build(); var config = new GlobalConfiguration.Builder() @@ -31,20 +31,20 @@ public void TestHttpClientSSLCertificateVerification_ExceptionResponse() var client = config.HttpClient; - var request = config.GlobalRequestBuilder() + var request = await config.GlobalRequestBuilder() .Setup(HttpMethod.Get, string.Empty) .Build(); // Act var ex = Assert.ThrowsAsync(() => client.ExecuteAsync(request)); Assert.AreEqual(expectedValue, ex.Message); - } - + } + [Test] public async Task TestHttpClientSkipSSLCertificateVerification_OKResponse() - { - var clientConfiguration = new CoreHttpClientConfiguration.Builder() - .SkipSslCertVerification(true) + { + var clientConfiguration = new CoreHttpClientConfiguration.Builder() + .SkipSslCertVerification(true) .Build(); var config = new GlobalConfiguration.Builder() @@ -58,7 +58,7 @@ public async Task TestHttpClientSkipSSLCertificateVerification_OKResponse() var client = config.HttpClient; - var request = config.GlobalRequestBuilder() + var request = await config.GlobalRequestBuilder() .Setup(HttpMethod.Get, string.Empty) .Build(); diff --git a/APIMatic.Core.Test/Http/HttpClientWrapperTest.cs b/APIMatic.Core.Test/Http/HttpClientWrapperTest.cs index 476dbce8..1692a6c4 100644 --- a/APIMatic.Core.Test/Http/HttpClientWrapperTest.cs +++ b/APIMatic.Core.Test/Http/HttpClientWrapperTest.cs @@ -40,7 +40,7 @@ public void SetupHttpClient() [Test] public async Task HttpClient_GetCall_200Response() { - var request = _config.GlobalRequestBuilder() + var request = await _config.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/httpclient/get/200") .Parameters(p => p .Body(b => b.Setup("Get Response"))) @@ -60,7 +60,7 @@ public async Task HttpClient_GetCall_200Response() [Test] public async Task TestHttpClientGetCall_400Response() { - var request = _config.GlobalRequestBuilder() + var request = await _config.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/httpclient/get/400") .Parameters(p => p .Body(b => b.Setup("Get Bad Request"))) @@ -84,7 +84,7 @@ public async Task TestHttpClientGetCall_200Response() var customHeaderKey = "Custom-Headder"; var customHeaderValue = "customHeader"; - var request = _config.GlobalRequestBuilder() + var request = await _config.GlobalRequestBuilder() .Setup(HttpMethod.Get, "/httpclient/get-combined-headers/200") .Build(); diff --git a/APIMatic.Core/APIMatic.Core.csproj b/APIMatic.Core/APIMatic.Core.csproj index b4f12e29..074173b0 100644 --- a/APIMatic.Core/APIMatic.Core.csproj +++ b/APIMatic.Core/APIMatic.Core.csproj @@ -20,7 +20,6 @@ APIMatic;dotnet;core;Core Library https://www.apimatic.io icon.png - 5d4cfd39-614d-4884-b9bc-d138d7d3d778