reuse one httpclient across entire plugin

This commit is contained in:
Stanley Dimant
2024-12-20 11:38:27 +01:00
parent 6d1cfed0ba
commit 34511e5f01
5 changed files with 33 additions and 24 deletions

View File

@@ -27,6 +27,9 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NReco.Logging.File; using NReco.Logging.File;
using System.Net.Http.Headers;
using System.Net.Http;
using System.Reflection;
namespace MareSynchronos; namespace MareSynchronos;
@@ -148,6 +151,13 @@ public sealed class Plugin : IDalamudPlugin
collection.AddSingleton((s) => new NotificationService(s.GetRequiredService<ILogger<NotificationService>>(), collection.AddSingleton((s) => new NotificationService(s.GetRequiredService<ILogger<NotificationService>>(),
s.GetRequiredService<MareMediator>(), s.GetRequiredService<DalamudUtilService>(), s.GetRequiredService<MareMediator>(), s.GetRequiredService<DalamudUtilService>(),
notificationManager, chatGui, s.GetRequiredService<MareConfigService>())); notificationManager, chatGui, s.GetRequiredService<MareConfigService>()));
collection.AddSingleton((s) =>
{
var httpClient = new HttpClient();
var ver = Assembly.GetExecutingAssembly().GetName().Version;
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build));
return httpClient;
});
collection.AddSingleton((s) => new MareConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new MareConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new ServerConfigService(pluginInterface.ConfigDirectory.FullName));
collection.AddSingleton((s) => new NotesConfigService(pluginInterface.ConfigDirectory.FullName)); collection.AddSingleton((s) => new NotesConfigService(pluginInterface.ConfigDirectory.FullName));

View File

@@ -18,6 +18,7 @@ public class ServerConfigurationManager
private readonly ServerConfigService _configService; private readonly ServerConfigService _configService;
private readonly DalamudUtilService _dalamudUtil; private readonly DalamudUtilService _dalamudUtil;
private readonly MareConfigService _mareConfigService; private readonly MareConfigService _mareConfigService;
private readonly HttpClient _httpClient;
private readonly ILogger<ServerConfigurationManager> _logger; private readonly ILogger<ServerConfigurationManager> _logger;
private readonly MareMediator _mareMediator; private readonly MareMediator _mareMediator;
private readonly NotesConfigService _notesConfig; private readonly NotesConfigService _notesConfig;
@@ -25,8 +26,7 @@ public class ServerConfigurationManager
public ServerConfigurationManager(ILogger<ServerConfigurationManager> logger, ServerConfigService configService, public ServerConfigurationManager(ILogger<ServerConfigurationManager> logger, ServerConfigService configService,
ServerTagConfigService serverTagConfig, NotesConfigService notesConfig, DalamudUtilService dalamudUtil, ServerTagConfigService serverTagConfig, NotesConfigService notesConfig, DalamudUtilService dalamudUtil,
MareConfigService mareConfigService, MareConfigService mareConfigService, HttpClient httpClient, MareMediator mareMediator)
MareMediator mareMediator)
{ {
_logger = logger; _logger = logger;
_configService = configService; _configService = configService;
@@ -34,6 +34,7 @@ public class ServerConfigurationManager
_notesConfig = notesConfig; _notesConfig = notesConfig;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_mareConfigService = mareConfigService; _mareConfigService = mareConfigService;
_httpClient = httpClient;
_mareMediator = mareMediator; _mareMediator = mareMediator;
EnsureMainExists(); EnsureMainExists();
} }
@@ -489,13 +490,12 @@ public class ServerConfigurationManager
public async Task<Dictionary<string, string>> GetUIDsWithDiscordToken(string serverUri, string token) public async Task<Dictionary<string, string>> GetUIDsWithDiscordToken(string serverUri, string token)
{ {
using HttpClient client = new HttpClient();
try try
{ {
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://"); var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
var oauthCheckUri = MareAuth.GetUIDsFullPath(new Uri(baseUri)); var oauthCheckUri = MareAuth.GetUIDsFullPath(new Uri(baseUri));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); _httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var response = await client.GetAsync(oauthCheckUri).ConfigureAwait(false); var response = await _httpClient.GetAsync(oauthCheckUri).ConfigureAwait(false);
var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(responseStream).ConfigureAwait(false) ?? []; return await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(responseStream).ConfigureAwait(false) ?? [];
} }
@@ -508,12 +508,11 @@ public class ServerConfigurationManager
public async Task<Uri?> CheckDiscordOAuth(string serverUri) public async Task<Uri?> CheckDiscordOAuth(string serverUri)
{ {
using HttpClient client = new HttpClient();
try try
{ {
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://"); var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
var oauthCheckUri = MareAuth.GetDiscordOAuthEndpointFullPath(new Uri(baseUri)); var oauthCheckUri = MareAuth.GetDiscordOAuthEndpointFullPath(new Uri(baseUri));
var response = await client.GetFromJsonAsync<Uri?>(oauthCheckUri).ConfigureAwait(false); var response = await _httpClient.GetFromJsonAsync<Uri?>(oauthCheckUri).ConfigureAwait(false);
return response; return response;
} }
catch (Exception ex) catch (Exception ex)
@@ -529,13 +528,14 @@ public class ServerConfigurationManager
Util.OpenLink(discordAuthUri.ToString() + "?sessionId=" + sessionId); Util.OpenLink(discordAuthUri.ToString() + "?sessionId=" + sessionId);
string? discordToken = null; string? discordToken = null;
using HttpClient client = new HttpClient(); using CancellationTokenSource timeOutCts = new();
client.Timeout = TimeSpan.FromSeconds(60); timeOutCts.CancelAfter(TimeSpan.FromSeconds(60));
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(timeOutCts.Token, token);
try try
{ {
var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://"); var baseUri = serverUri.Replace("wss://", "https://").Replace("ws://", "http://");
var oauthCheckUri = MareAuth.GetDiscordOAuthTokenFullPath(new Uri(baseUri), sessionId); var oauthCheckUri = MareAuth.GetDiscordOAuthTokenFullPath(new Uri(baseUri), sessionId);
var response = await client.GetAsync(oauthCheckUri, token).ConfigureAwait(false); var response = await _httpClient.GetAsync(oauthCheckUri, linkedCts.Token).ConfigureAwait(false);
discordToken = await response.Content.ReadAsStringAsync().ConfigureAwait(false); discordToken = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -26,6 +26,7 @@ using Microsoft.Extensions.Logging;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Net.Http.Headers;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Numerics; using System.Numerics;
using System.Text; using System.Text;
@@ -40,6 +41,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
private readonly MareConfigService _configService; private readonly MareConfigService _configService;
private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new(); private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new();
private readonly DalamudUtilService _dalamudUtilService; private readonly DalamudUtilService _dalamudUtilService;
private readonly HttpClient _httpClient;
private readonly FileCacheManager _fileCacheManager; private readonly FileCacheManager _fileCacheManager;
private readonly FileCompactor _fileCompactor; private readonly FileCompactor _fileCompactor;
private readonly FileUploadManager _fileTransferManager; private readonly FileUploadManager _fileTransferManager;
@@ -78,7 +80,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
FileCacheManager fileCacheManager, FileCacheManager fileCacheManager,
FileCompactor fileCompactor, ApiController apiController, FileCompactor fileCompactor, ApiController apiController,
IpcManager ipcManager, CacheMonitor cacheMonitor, IpcManager ipcManager, CacheMonitor cacheMonitor,
DalamudUtilService dalamudUtilService) : base(logger, mediator, "Mare Synchronos Settings", performanceCollector) DalamudUtilService dalamudUtilService, HttpClient httpClient) : base(logger, mediator, "Mare Synchronos Settings", performanceCollector)
{ {
_configService = configService; _configService = configService;
_mareCharaFileManager = mareCharaFileManager; _mareCharaFileManager = mareCharaFileManager;
@@ -93,6 +95,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
_ipcManager = ipcManager; _ipcManager = ipcManager;
_cacheMonitor = cacheMonitor; _cacheMonitor = cacheMonitor;
_dalamudUtilService = dalamudUtilService; _dalamudUtilService = dalamudUtilService;
_httpClient = httpClient;
_fileCompactor = fileCompactor; _fileCompactor = fileCompactor;
_uiShared = uiShared; _uiShared = uiShared;
AllowClickthrough = false; AllowClickthrough = false;
@@ -1833,13 +1836,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
return (false, false, $"Failed to convert {failedConversions.Count} entries: " + string.Join(", ", failedConversions.Select(k => k.CharacterName))); return (false, false, $"Failed to convert {failedConversions.Count} entries: " + string.Join(", ", failedConversions.Select(k => k.CharacterName)));
} }
using HttpClient client = new();
var baseUri = serverStorage.ServerUri.Replace("wss://", "https://").Replace("ws://", "http://"); var baseUri = serverStorage.ServerUri.Replace("wss://", "https://").Replace("ws://", "http://");
var oauthCheckUri = MareAuth.GetUIDsBasedOnSecretKeyFullPath(new Uri(baseUri)); var oauthCheckUri = MareAuth.GetUIDsBasedOnSecretKeyFullPath(new Uri(baseUri));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", serverStorage.OAuthToken);
var requestContent = JsonContent.Create(secretKeyMapping.Select(k => k.Key).ToList()); var requestContent = JsonContent.Create(secretKeyMapping.Select(k => k.Key).ToList());
using var response = await client.PostAsync(oauthCheckUri, requestContent, token).ConfigureAwait(false); HttpRequestMessage requestMessage = new(HttpMethod.Post, oauthCheckUri);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", serverStorage.OAuthToken);
requestMessage.Content = requestContent;
using var response = await _httpClient.SendAsync(requestMessage, token).ConfigureAwait(false);
Dictionary<string, string>? secretKeyUidMapping = await JsonSerializer.DeserializeAsync<Dictionary<string, string>> Dictionary<string, string>? secretKeyUidMapping = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>
(await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false), cancellationToken: token).ConfigureAwait(false); (await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false), cancellationToken: token).ConfigureAwait(false);
if (secretKeyUidMapping == null) if (secretKeyUidMapping == null)

View File

@@ -22,14 +22,11 @@ public class FileTransferOrchestrator : DisposableMediatorSubscriberBase
private int CurrentlyUsedDownloadSlots => _availableDownloadSlots - _downloadSemaphore.CurrentCount; private int CurrentlyUsedDownloadSlots => _availableDownloadSlots - _downloadSemaphore.CurrentCount;
public FileTransferOrchestrator(ILogger<FileTransferOrchestrator> logger, MareConfigService mareConfig, public FileTransferOrchestrator(ILogger<FileTransferOrchestrator> logger, MareConfigService mareConfig,
MareMediator mediator, TokenProvider tokenProvider) : base(logger, mediator) MareMediator mediator, TokenProvider tokenProvider, HttpClient httpClient) : base(logger, mediator)
{ {
_mareConfig = mareConfig; _mareConfig = mareConfig;
_tokenProvider = tokenProvider; _tokenProvider = tokenProvider;
_httpClient = new() _httpClient = httpClient;
{
Timeout = TimeSpan.FromSeconds(3000)
};
var ver = Assembly.GetExecutingAssembly().GetName().Version; var ver = Assembly.GetExecutingAssembly().GetName().Version;
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build)); _httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build));

View File

@@ -20,14 +20,14 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
private readonly ServerConfigurationManager _serverManager; private readonly ServerConfigurationManager _serverManager;
private readonly ConcurrentDictionary<JwtIdentifier, string> _tokenCache = new(); private readonly ConcurrentDictionary<JwtIdentifier, string> _tokenCache = new();
public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager, DalamudUtilService dalamudUtil, MareMediator mareMediator) public TokenProvider(ILogger<TokenProvider> logger, ServerConfigurationManager serverManager, DalamudUtilService dalamudUtil, MareMediator mareMediator, HttpClient httpClient)
{ {
_logger = logger; _logger = logger;
_serverManager = serverManager; _serverManager = serverManager;
_dalamudUtil = dalamudUtil; _dalamudUtil = dalamudUtil;
_httpClient = new();
var ver = Assembly.GetExecutingAssembly().GetName().Version; var ver = Assembly.GetExecutingAssembly().GetName().Version;
Mediator = mareMediator; Mediator = mareMediator;
_httpClient = httpClient;
Mediator.Subscribe<DalamudLogoutMessage>(this, (_) => Mediator.Subscribe<DalamudLogoutMessage>(this, (_) =>
{ {
_lastJwtIdentifier = null; _lastJwtIdentifier = null;
@@ -38,7 +38,6 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
_lastJwtIdentifier = null; _lastJwtIdentifier = null;
_tokenCache.Clear(); _tokenCache.Clear();
}); });
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MareSynchronos", ver!.Major + "." + ver!.Minor + "." + ver!.Build));
} }
public MareMediator Mediator { get; } public MareMediator Mediator { get; }
@@ -48,7 +47,6 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber
public void Dispose() public void Dispose()
{ {
Mediator.UnsubscribeAll(this); Mediator.UnsubscribeAll(this);
_httpClient.Dispose();
} }
public async Task<string> GetNewToken(bool isRenewal, JwtIdentifier identifier, CancellationToken ct) public async Task<string> GetNewToken(bool isRenewal, JwtIdentifier identifier, CancellationToken ct)