Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Customization of Base URI #10

Open
Foxtrek64 opened this issue Jul 7, 2022 · 3 comments
Open

Allow Customization of Base URI #10

Foxtrek64 opened this issue Jul 7, 2022 · 3 comments

Comments

@Foxtrek64
Copy link
Contributor

Description

Some REST APIs will specify a specific API server instance after authenticating and will expect all API requests to use that server.

For instance, authentication may take place at auth.example.com but the upon successful authentication, you are directed to send API queries to api-na1.example.com.

The ability to customize the base address should be added.

_restClient.WithCustomization
(
    x =>
    {
        x.BaseAddress = authResponse.ResourceServerBaseUri;
        x.AddHeader("Authorization", $"bearer {authResponse.AccessToken}");
    }
);

Why This is Needed

Without the ability to customize the base address, it places a requirement on the user to fully qualify all endpoint calls, which becomes difficult when the directed API base address changes between calls.

Alternatives Considered

One option currently is for the user to do something like this, where _cache is an IMemoryCache and IAuthenticationResponse.ResourceServerBaseUri is the API base address I was directed to use. However, for obvious reasons, this is less than ideal.

/// <summary>
/// Returns a list of agents currently configured in the business unit.
/// </summary>
/// <param name="startDate">The earliest date to look for agents.</param>
/// <param name="cancellationToken">A cancellation token for this operation.</param>
/// <returns>A list of agents from the API.</returns>
public async Task<Result<IGetAgentsResult>> DownloadAgentListAsync(DateTime startDate, CancellationToken cancellationToken = default)
{
    var currentAuthSession = _cache.Get<IAuthenticationResponse>(InContactAuthResponse);
    return await _restClient.GetAsync<IGetAgentsResult>
        (
            $"{currentAuthSession.ResourceServerBaseUri}inContactAPI/services/{_config.ApiVersion}/agents",
            builder =>
            {
                builder.WithJson(json =>
                {
                    json.Write("updatedSince", startDate.ToString("O", CultureInfo.InvariantCulture), _jsonOptions);
                    json.Write("isActive", true, _jsonOptions);
                    json.Write("searchString", _optionalString, _jsonOptions);
                    json.Write("fields", "agentId, userName, firstName, lastName, userId, teamId", _jsonOptions);
                });
            },
            ct: cancellationToken
        );
}
@MazeXP
Copy link
Contributor

MazeXP commented Jul 22, 2022

The problem is that HttpClient does not allow to change the BaseAddress after the first request has been made.

Therefore one viable alternative would be to use the following DelegatingHandler attached to the HttpClient of the RestClient.
An example for attaching a DelegatingHandler to a RestClient can be found here: link

public class BaseAddressStore
{
    public Uri? BaseAddress { get; set; } // Consider Optional

    public BaseAddressStore(Uri? baseAddress = null)
    {
        this.BaseAddress = baseAddress;
    }
}

public class BaseAddressOverrideHandler : System.Net.Http.DelegatingHandler
{
    private readonly Uri _originalBaseAddress;
    private readonly BaseAddressStore _baseAddressStore;

    public BaseAddressOverrideHandler(Uri orignalBaseAddress, BaseAddressStore baseAddressStore)
    {
        _originalBaseAddress = originalBaseAddress;
        _baseAddressStore = baseAddressStore;
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var baseAddress = _baseAddressStore.BaseAddress;
        if (baseAddress != null && request.RequestUri != null)
        {
            if (_originalBaseAddress.IsBaseOf(request.RequestUri))
            {
                var relativeUri = _originalBaseAddress.MakeRelativeUri(request.RequestUri);
                request.RequestUri = new Uri(baseAddress, relativeUri);
            }
        }

        return base.SendAsync(request, cancellationToken);
    }
}

@Nihlus
Copy link
Member

Nihlus commented Jul 22, 2022

I'm not sure if that is a problem, since a new HttpClient is requested from the factory on each request.

@Foxtrek64
Copy link
Contributor Author

HttpClientFactory doesn't allow for modifying the base address configuration, likely due to some issues with how it handles the lifetime (and possible reuse) of existing clients. There is no tracking mechanism for which clients which use which base address since it's assumed that this configuration will not change.

I think @MazeXP's suggestion is likely the most practical at this point, though I'm doing some digging to see if there are other options (besides implementing our own HttpClientFactory).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants