diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationService.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationService.cs index 5db4a3a38b..d9c71e0ea2 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationService.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/Authentication/RemoteAppAuthenticationService.cs @@ -30,21 +30,15 @@ internal partial class RemoteAppAuthenticationService : IRemoteAppAuthentication private RemoteAppAuthenticationClientOptions? _options; public RemoteAppAuthenticationService( - IHttpClientFactory httpClientFactory, IAuthenticationResultFactory resultFactory, IOptionsSnapshot authOptions, IOptions remoteAppOptions, ILogger logger) { - if (httpClientFactory is null) - { - throw new ArgumentNullException(nameof(httpClientFactory)); - } - _resultFactory = resultFactory ?? throw new ArgumentNullException(nameof(resultFactory)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _authOptionsSnapshot = authOptions ?? throw new ArgumentNullException(nameof(authOptions)); - _client = httpClientFactory.CreateClient(RemoteConstants.HttpClientName); + _client = remoteAppOptions?.Value.BackchannelClient ?? throw new ArgumentNullException(nameof(remoteAppOptions)); } /// diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientExtensions.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientExtensions.cs index 2a3812868f..a34b0af6ff 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientExtensions.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientExtensions.cs @@ -26,31 +26,11 @@ public static ISystemWebAdapterRemoteClientAppBuilder AddRemoteAppClient(this IS throw new ArgumentNullException(nameof(configure)); } + builder.Services.AddSingleton, RemoteAppClientPostConfigureOptions>(); builder.Services.AddOptions() .Configure(configure) .ValidateDataAnnotations(); - builder.Services.AddHttpClient(RemoteConstants.HttpClientName) - .ConfigurePrimaryHttpMessageHandler(sp => - { - var options = sp.GetRequiredService>().Value; - - if (options.BackchannelHandler is { } handler) - { - return handler; - } - - // Disable cookies in the HTTP client because the service will manage the cookie header directly - return new HttpClientHandler { UseCookies = false, AllowAutoRedirect = false }; - }) - .ConfigureHttpClient((sp, client) => - { - var options = sp.GetRequiredService>().Value; - - client.BaseAddress = options.RemoteAppUrl; - client.DefaultRequestHeaders.Add(options.ApiKeyHeader, options.ApiKey); - }); - return new Builder(builder.Services); } diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientOptions.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientOptions.cs index ee4e5674cb..6b03612735 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientOptions.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientOptions.cs @@ -53,7 +53,12 @@ public Uri RemoteAppUrl } /// - /// Gets or sets an to use for making requests to the remote app. + /// Gets or sets an to use for making requests to the remote app. Used if BackchannelClient is null. /// public HttpMessageHandler? BackchannelHandler { get; set; } + + /// + /// Gets or sets an to use for making requests to the remote app. + /// + public HttpClient? BackchannelClient { get; set; } } diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientPostConfigureOptions.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientPostConfigureOptions.cs new file mode 100644 index 0000000000..bb1438c3b5 --- /dev/null +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/RemoteAppClientPostConfigureOptions.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net.Http; +using Microsoft.AspNetCore.SystemWebAdapters; +using Microsoft.Extensions.Options; + +namespace Microsoft.Extensions.DependencyInjection; + +internal class RemoteAppClientPostConfigureOptions : IPostConfigureOptions +{ + public void PostConfigure(string name, RemoteAppClientOptions options) + { + if (options.BackchannelClient is null) + { + options.BackchannelClient = new HttpClient( + options.BackchannelHandler + // Disable cookies in the HTTP client because the service will manage the cookie header directly + ?? new HttpClientHandler { UseCookies = false, AllowAutoRedirect = false }); + + // Set base address and API key header based on options + if (options.RemoteAppUrl is not null) + { + options.BackchannelClient.BaseAddress = options.RemoteAppUrl; + } + + if (!string.IsNullOrEmpty(options.ApiKeyHeader)) + { + options.BackchannelClient.DefaultRequestHeaders.Add(options.ApiKeyHeader, options.ApiKey); + } + } + } +} diff --git a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs index fdaea50d42..b81f0ddd4c 100644 --- a/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs +++ b/src/Microsoft.AspNetCore.SystemWebAdapters.CoreServices/SessionState/RemoteSession/RemoteAppSessionStateManager.cs @@ -17,20 +17,20 @@ namespace Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession; internal partial class RemoteAppSessionStateManager : ISessionManager { - private readonly IHttpClientFactory _httpClientFactory; private readonly ISessionSerializer _serializer; private readonly ILogger _logger; private readonly RemoteAppSessionStateClientOptions _options; + private readonly HttpClient _backchannelClient; public RemoteAppSessionStateManager( - IHttpClientFactory httpClientFactory, ISessionSerializer serializer, IOptions options, + IOptions remoteAppClientOptions, ILogger logger) { _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); + _backchannelClient = remoteAppClientOptions?.Value.BackchannelClient ?? throw new ArgumentNullException(nameof(remoteAppClientOptions)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory)); _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); } @@ -79,8 +79,7 @@ private async Task GetSessionDataAsync(string? sessionId, bool re AddSessionCookieToHeader(req, sessionId); AddReadOnlyHeader(req, readOnly); - using var client = _httpClientFactory.CreateClient(RemoteConstants.HttpClientName); - var response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, token); + var response = await _backchannelClient.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, token); LogRetrieveResponse(response.StatusCode); @@ -120,8 +119,7 @@ private async Task SetOrReleaseSessionData(ISessionState? state, CancellationTok req.Content = new SerializedSessionHttpContent(_serializer, state); } - using var client = _httpClientFactory.CreateClient(RemoteConstants.HttpClientName); - using var response = await client.SendAsync(req, cancellationToken); + using var response = await _backchannelClient.SendAsync(req, cancellationToken); LogCommitResponse(response.StatusCode); diff --git a/src/Services/RemoteConstants.cs b/src/Services/RemoteConstants.cs index f3622da6b3..8c040f3b54 100644 --- a/src/Services/RemoteConstants.cs +++ b/src/Services/RemoteConstants.cs @@ -6,6 +6,4 @@ namespace Microsoft.AspNetCore.SystemWebAdapters; internal static class RemoteConstants { internal const string ApiKeyHeaderName = "X-SystemWebAdapter-RemoteAppAuthentication-Key"; - - internal const string HttpClientName = "remote-client"; }