@@ -17,26 +17,42 @@ namespace Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession;
1717
1818internal partial class RemoteAppSessionStateManager : ISessionManager
1919{
20- private readonly HttpClient _client ;
20+ private readonly IHttpClientFactory _httpClientFactory ;
2121 private readonly ISessionSerializer _serializer ;
2222 private readonly ILogger < RemoteAppSessionStateManager > _logger ;
2323 private readonly RemoteAppSessionStateClientOptions _options ;
24+ private readonly IOptions < RemoteAppOptions > _remoteAppOptions ;
25+ private HttpClient ? _client ;
26+
27+ private HttpClient Client
28+ {
29+ get
30+ {
31+ if ( _client is null )
32+ {
33+ // Use the HttpClient supplied in options if one is present in options;
34+ // otherwise, generate a client with an IHttpClientFactory from DI
35+ _client = _remoteAppOptions . Value . BackchannelHttpClient ?? _httpClientFactory . CreateClient ( SessionConstants . SessionClientName ) ;
36+ _client . BaseAddress = new Uri ( $ "{ _remoteAppOptions . Value . RemoteAppUrl . ToString ( ) . TrimEnd ( '/' ) } { _options . SessionEndpointPath } ") ;
37+ _client . DefaultRequestHeaders . Add ( _remoteAppOptions . Value . ApiKeyHeader , _remoteAppOptions . Value . ApiKey ) ;
38+ }
39+
40+ return _client ;
41+ }
42+ }
2443
2544 public RemoteAppSessionStateManager (
26- HttpClient client ,
45+ IHttpClientFactory httpClientFactory ,
2746 ISessionSerializer serializer ,
2847 IOptions < RemoteAppSessionStateClientOptions > sessionOptions ,
2948 IOptions < RemoteAppOptions > remoteAppOptions ,
3049 ILogger < RemoteAppSessionStateManager > logger )
3150 {
32- _client = client ?? throw new ArgumentNullException ( nameof ( client ) ) ;
33- _logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
51+ _remoteAppOptions = remoteAppOptions ?? throw new ArgumentNullException ( nameof ( remoteAppOptions ) ) ;
3452 _options = sessionOptions ? . Value ?? throw new ArgumentNullException ( nameof ( sessionOptions ) ) ;
53+ _logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
54+ _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException ( nameof ( httpClientFactory ) ) ;
3555 _serializer = serializer ?? throw new ArgumentNullException ( nameof ( serializer ) ) ;
36-
37- var remoteOptions = remoteAppOptions ? . Value ?? throw new ArgumentNullException ( nameof ( remoteAppOptions ) ) ;
38- _client . BaseAddress = new Uri ( remoteOptions . RemoteAppUrl , _options . SessionEndpointPath ) ;
39- _client . DefaultRequestHeaders . Add ( remoteOptions . ApiKeyHeader , remoteOptions . ApiKey ) ;
4056 }
4157
4258 [ LoggerMessage ( EventId = 0 , Level = LogLevel . Debug , Message = "Loaded {Count} items from remote session state for session {SessionId}" ) ]
@@ -53,9 +69,6 @@ public RemoteAppSessionStateManager(
5369
5470 public async Task < ISessionState > CreateAsync ( HttpContextCore context , SessionAttribute metadata )
5571 {
56- using var timeout = new CancellationTokenSource ( _options . NetworkTimeout ) ;
57- using var cts = CancellationTokenSource . CreateLinkedTokenSource ( timeout . Token , context . RequestAborted , context . RequestAborted ) ;
58-
5972 // If an existing remote session ID is present in the request, use its session ID.
6073 // Otherwise, leave session ID null for now; it will be provided by the remote service
6174 // when session data is loaded.
@@ -64,7 +77,7 @@ public async Task<ISessionState> CreateAsync(HttpContextCore context, SessionAtt
6477 try
6578 {
6679 // Get or create session data
67- var response = await GetSessionDataAsync ( sessionId , metadata . IsReadOnly , context , cts . Token ) ;
80+ var response = await GetSessionDataAsync ( sessionId , metadata . IsReadOnly , context , context . RequestAborted ) ;
6881
6982 LogSessionLoad ( response . Count , response . SessionID ) ;
7083
@@ -87,7 +100,7 @@ private async Task<ISessionState> GetSessionDataAsync(string? sessionId, bool re
87100 AddSessionCookieToHeader ( req , sessionId ) ;
88101 AddReadOnlyHeader ( req , readOnly ) ;
89102
90- var response = await _client . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead , token ) ;
103+ var response = await Client . SendAsync ( req , HttpCompletionOption . ResponseHeadersRead , token ) ;
91104
92105 LogRetrieveResponse ( response . StatusCode ) ;
93106
@@ -119,9 +132,6 @@ private async Task<ISessionState> GetSessionDataAsync(string? sessionId, bool re
119132 /// </summary>
120133 private async Task SetOrReleaseSessionData ( ISessionState ? state , CancellationToken cancellationToken )
121134 {
122- using var timeout = new CancellationTokenSource ( _options . NetworkTimeout ) ;
123- using var cts = CancellationTokenSource . CreateLinkedTokenSource ( timeout . Token , cancellationToken ) ;
124-
125135 using var req = new HttpRequestMessage { Method = HttpMethod . Put } ;
126136
127137 if ( state is not null )
@@ -130,7 +140,7 @@ private async Task SetOrReleaseSessionData(ISessionState? state, CancellationTok
130140 req . Content = new SerializedSessionHttpContent ( _serializer , state ) ;
131141 }
132142
133- using var response = await _client . SendAsync ( req , cts . Token ) ;
143+ using var response = await Client . SendAsync ( req , cancellationToken ) ;
134144
135145 LogCommitResponse ( response . StatusCode ) ;
136146
0 commit comments