Skip to content

Commit

Permalink
feat: allow Vonage Urls to include a relative path
Browse files Browse the repository at this point in the history
Note: it should have been possible from the start, but '/' were badly handled in ApiRequest
  • Loading branch information
Tr00d committed Dec 16, 2024
1 parent dbab981 commit 81ab4da
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 100 deletions.
36 changes: 36 additions & 0 deletions Vonage.Test/Request/ApiRequestTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#region
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Vonage.Accounts;
using Vonage.Request;
using WireMock.ResponseBuilders;
using WireMock.Server;
using Xunit;
#endregion

namespace Vonage.Test.Request;

public class ApiRequestTest : TestBase
{
[Fact]
public async Task Configuration_ShouldAllowCustomBaseUri()
{
var server = WireMockServer.Start();
server.Given(WireMock.RequestBuilders.Request.Create()
.WithPath("/rest/account/get-balance")
.UsingGet())
.RespondWith(Response.Create()
.WithBodyAsJson(new Balance())
.WithStatusCode(HttpStatusCode.OK));
this.configuration = Configuration.FromConfiguration(new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
{"vonage:Url.Rest", $"{server.Url}/rest"},
})
.Build());
var client = this.BuildVonageClient(Credentials.FromApiKeyAndSecret(this.ApiKey, this.ApiSecret));
await client.AccountClient.GetAccountBalanceAsync();
}
}
2 changes: 1 addition & 1 deletion Vonage.Test/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class TestBase
#endif

private static readonly string TestAssemblyName = ThisAssembly.GetName().Name;
protected readonly Configuration configuration;
protected Configuration configuration;

protected VonageClient BuildVonageClient(Credentials credentials) =>
new VonageClient(credentials, this.configuration, new TimeProvider());
Expand Down
6 changes: 3 additions & 3 deletions Vonage/Accounts/AccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public Task<AccountSettingsResult> ChangeAccountSettingsAsync(AccountSettingsReq
ApiRequest.Build(this.GetCredentials(creds), this.configuration, this.timeProvider)
.DoPostRequestUrlContentFromObjectAsync<AccountSettingsResult>
(
ApiRequest.GetBaseUriFor(this.configuration, "/account/settings"),
ApiRequest.GetBaseUri(ApiRequest.UriType.Rest, this.configuration, "/account/settings"),
request
);

Expand All @@ -52,7 +52,7 @@ public Task<Secret> CreateApiSecretAsync(CreateSecretRequest request, string api
public Task<Balance> GetAccountBalanceAsync(Credentials creds = null) =>
ApiRequest.Build(this.GetCredentials(creds), this.configuration, this.timeProvider)
.DoGetRequestWithQueryParametersAsync<Balance>(
ApiRequest.GetBaseUriFor(this.configuration, "/account/get-balance"),
ApiRequest.GetBaseUri(ApiRequest.UriType.Rest, this.configuration, "/account/get-balance"),
AuthType.Basic);

/// <inheritdoc />
Expand Down Expand Up @@ -89,7 +89,7 @@ await ApiRequest.Build(this.GetCredentials(creds), this.configuration, this.time
public Task<TopUpResult> TopUpAccountBalanceAsync(TopUpRequest request, Credentials creds = null) =>
ApiRequest.Build(this.GetCredentials(creds), this.configuration, this.timeProvider)
.DoGetRequestWithQueryParametersAsync<TopUpResult>(
ApiRequest.GetBaseUriFor(this.configuration, "/account/top-up"),
ApiRequest.GetBaseUri(ApiRequest.UriType.Rest, this.configuration, "/account/top-up"),
AuthType.Basic,
request
);
Expand Down
88 changes: 45 additions & 43 deletions Vonage/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
#region
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
Expand All @@ -10,6 +11,7 @@
using Vonage.Cryptography;
using Vonage.Logger;
using Vonage.Request;
#endregion

namespace Vonage;

Expand All @@ -22,6 +24,27 @@ public sealed class Configuration
private const int DefaultPooledConnectionLifetime = 600;
private const string LoggerCategory = "Vonage.Configuration";

static Configuration()
{
}

private Configuration(IConfiguration configuration)
{
this.Settings = configuration;
this.LogAuthenticationCapabilities(LogProvider.GetLogger(LoggerCategory));
this.ClientHandler = this.BuildDefaultHandler();
}

internal Configuration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("settings.json", true, true)
.AddJsonFile("appsettings.json", true, true);
this.Settings = builder.Build();
this.LogAuthenticationCapabilities(LogProvider.GetLogger(LoggerCategory));
this.ClientHandler = this.BuildDefaultHandler();
}

private static Maybe<double> RequestsPerSecond =>
double.TryParse(Instance.Settings["vonage:RequestsPerSecond"], out var requestsPerSecond)
? requestsPerSecond
Expand All @@ -37,17 +60,6 @@ public sealed class Configuration
? idleTimeout
: DefaultPooledConnectionLifetime);

static Configuration()
{
}

private Configuration(IConfiguration configuration)
{
this.Settings = configuration;
this.LogAuthenticationCapabilities(LogProvider.GetLogger(LoggerCategory));
this.ClientHandler = this.BuildDefaultHandler();
}

/// <summary>
/// Retrieves the Api secret.
/// </summary>
Expand Down Expand Up @@ -132,16 +144,6 @@ public HttpClient Client
/// </summary>
public VonageUrls VonageUrls => VonageUrls.FromConfiguration(this.Settings);

internal Configuration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("settings.json", true, true)
.AddJsonFile("appsettings.json", true, true);
this.Settings = builder.Build();
this.LogAuthenticationCapabilities(LogProvider.GetLogger(LoggerCategory));
this.ClientHandler = this.BuildDefaultHandler();
}

/// <summary>
/// Builds a Credentials from the current Configuration.
/// </summary>
Expand Down Expand Up @@ -268,6 +270,23 @@ internal HttpClient BuildHttpClient(Uri baseUri)
/// </summary>
public readonly struct VonageUrls
{
/// <summary>
/// </summary>
public enum Region
{
/// <summary>
/// </summary>
[Description("AMER")] US,

/// <summary>
/// </summary>
[Description("EMEA")] EU,

/// <summary>
/// </summary>
[Description("APAC")] APAC,
}

private const string DefaultApiUrlApac = "https://api-ap.vonage.com";
private const string DefaultApiUrlEu = "https://api-eu.vonage.com";
private const string DefaultApiUrlUs = "https://api-us.vonage.com";
Expand All @@ -280,15 +299,15 @@ public readonly struct VonageUrls
internal const string OidcApiKey = "vonage:Url.OIDC";
internal const string VideoApiKey = "vonage:Url.Api.Video";

private readonly IConfiguration configuration;

private readonly Dictionary<Region, string> regions = new Dictionary<Region, string>
{
{Region.US, DefaultApiUrlUs},
{Region.EU, DefaultApiUrlEu},
{Region.APAC, DefaultApiUrlApac},
};

private readonly IConfiguration configuration;

private VonageUrls(IConfiguration configuration) => this.configuration = configuration;

/// <summary>
Expand Down Expand Up @@ -327,23 +346,6 @@ public Uri Get(Region region) =>
this.Evaluate(string.Concat(NexmoApiKey, ".", region.AsString(EnumFormat.Description)), this.regions[region]);

private Uri Evaluate(string key, string defaultValue) => this.configuration[key] is null
? new Uri(defaultValue)
: new Uri(this.configuration[key]);

/// <summary>
/// </summary>
public enum Region
{
/// <summary>
/// </summary>
[Description("AMER")] US,

/// <summary>
/// </summary>
[Description("EMEA")] EU,

/// <summary>
/// </summary>
[Description("APAC")] APAC,
}
? new Uri($"{defaultValue.TrimEnd('/')}/")
: new Uri($"{this.configuration[key].TrimEnd('/')}/");
}
Loading

0 comments on commit 81ab4da

Please sign in to comment.