Skip to content

Commit

Permalink
provide an httpclient generator, to control reuse and dynamically cha…
Browse files Browse the repository at this point in the history
…nging base url
  • Loading branch information
dit-zy committed Aug 18, 2024
1 parent 063145a commit 448c760
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 35 deletions.
18 changes: 9 additions & 9 deletions ScoutHelper/Managers/BearManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using CSharpFunctionalExtensions;
using Dalamud.Plugin.Services;
Expand All @@ -19,19 +18,25 @@ namespace ScoutHelper.Managers;
public class BearManager : IDisposable {
private readonly IPluginLog _log;
private readonly Configuration _conf;
private readonly HttpClient _httpClient = new();
private readonly HttpClientGenerator _httpClientGenerator;

private IDictionary<uint, (Patch patch, string name)> MobIdToBearName { get; init; }

public BearManager(IPluginLog log, Configuration conf, ScoutHelperOptions options) {
_log = log;
_conf = conf;

_httpClientGenerator = new HttpClientGenerator(
_log,
() => _conf.BearApiBaseUrl,
client => client.Timeout = _conf.BearApiTimeout
);

MobIdToBearName = LoadData(options.BearDataFile);
}

public void Dispose() {
_httpClient.Dispose();
_httpClientGenerator.Dispose();

GC.SuppressFinalize(this);
}
Expand All @@ -52,13 +57,8 @@ IEnumerable<TrainMob> trainMobs

return await HttpUtils.DoRequest<BearApiTrainRequest, BearApiTrainResponse, BearLinkData>(
_log,
_httpClient,
_conf.BearApiBaseUrl,
new BearApiTrainRequest(worldName, _conf.BearTrainName, highestPatch.BearName(), spawnPoints),
(client, content) => {
client.Timeout = _conf.BearApiTimeout;
return client.PostAsync(_conf.BearApiTrainPath, content);
},
(content) => _httpClientGenerator.Client.PostAsync(_conf.BearApiTrainPath, content),
bearResponse => new BearLinkData(
$"{_conf.BearSiteTrainUrl}/{bearResponse.Trains.First().TrainId}",
bearResponse.Trains.First().Password,
Expand Down
25 changes: 10 additions & 15 deletions ScoutHelper/Managers/TurtleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CSharpFunctionalExtensions;
Expand Down Expand Up @@ -30,7 +29,7 @@ public partial class TurtleManager : IDisposable {
private readonly IPluginLog _log;
private readonly Configuration _conf;
private readonly IClientState _clientState;
private readonly HttpClient _httpClient = new();
private readonly HttpClientGenerator _httpClientGenerator;

private MobDict MobIdToTurtleId { get; }
private TerritoryDict TerritoryIdToTurtleData { get; }
Expand All @@ -52,12 +51,18 @@ MobManager mobManager
_conf = conf;
_clientState = clientState;

_httpClientGenerator = new HttpClientGenerator(
_log,
() => _conf.TurtleApiBaseUrl,
client => client.Timeout = _conf.TurtleApiTimeout
);

(MobIdToTurtleId, TerritoryIdToTurtleData)
= LoadData(options.TurtleDataFile, territoryManager, mobManager);
}

public void Dispose() {
_httpClient.Dispose();
_httpClientGenerator.Dispose();

GC.SuppressFinalize(this);
}
Expand Down Expand Up @@ -88,8 +93,6 @@ public async Task<TurtleHttpStatus> UpdateCurrentSession(IList<TrainMob> train)
var httpResult = await
HttpUtils.DoRequest(
_log,
_httpClient,
_conf.TurtleApiBaseUrl,
new TurtleTrainUpdateRequest(
_currentCollabPassword,
_clientState.PlayerTag().Where(_ => _conf.IncludeNameInTurtleSession),
Expand All @@ -101,10 +104,7 @@ public async Task<TurtleHttpStatus> UpdateCurrentSession(IList<TrainMob> train)
mob.Position)
)
),
(client, content) => {
client.Timeout = _conf.TurtleApiTimeout;
return client.PatchAsync($"{_conf.TurtleApiTrainPath}/{_currentCollabSession}", content);
}
( content) => _httpClientGenerator.Client.PatchAsync($"{_conf.TurtleApiTrainPath}/{_currentCollabSession}", content)
).TapError(
error => {
if (error.ErrorType == HttpErrorType.Timeout) {
Expand Down Expand Up @@ -139,13 +139,8 @@ public async Task<Result<TurtleLinkData, string>> GenerateTurtleLink(

return await HttpUtils.DoRequest<TurtleTrainRequest, TurtleTrainResponse, TurtleLinkData>(
_log,
_httpClient,
_conf.TurtleApiBaseUrl,
TurtleTrainRequest.CreateRequest(spawnPoints),
(client, content) => {
client.Timeout = _conf.TurtleApiTimeout;
return client.PostAsync(_conf.TurtleApiTrainPath, content);
},
( content) => _httpClientGenerator.Client.PostAsync(_conf.TurtleApiTrainPath, content),
trainResponse => TurtleLinkData.From(trainResponse, highestPatch)
)
.HandleHttpError(
Expand Down
50 changes: 50 additions & 0 deletions ScoutHelper/Utils/HttpClientGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Net.Http;
using Dalamud.Plugin.Services;

namespace ScoutHelper.Utils;

public class HttpClientGenerator : IDisposable {
private readonly IPluginLog _log;
private readonly Func<string> _baseUrlSupplier;
private readonly Action<HttpClient> _clientConfigurer;

private HttpClient _client = new();

public HttpClient Client {
get {
var latestUrl = _baseUrlSupplier().AsUri();
if (_client.BaseAddress != latestUrl) {
InitializeNewClient();
}

return _client;
}
}

public HttpClientGenerator(IPluginLog log, Func<string> baseUrlSupplier, Action<HttpClient> clientConfigurer) {
_log = log;
_baseUrlSupplier = baseUrlSupplier;
_clientConfigurer = clientConfigurer;

InitializeNewClient();
}

public void Dispose() {
_client.Dispose();

GC.SuppressFinalize(this);
}

private void InitializeNewClient() {
var client = new HttpClient();
client.BaseAddress = _baseUrlSupplier().AsUri();
_log.Debug("generating a new http client for base address: {0:l}", client.BaseAddress.ToString());
client.DefaultRequestHeaders.UserAgent.Add(Constants.UserAgent);
client.DefaultRequestHeaders.Accept.Add(Constants.MediaTypeJson);
_clientConfigurer(client);

_client.Dispose();
_client = client;
}
}
15 changes: 4 additions & 11 deletions ScoutHelper/Utils/HttpUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ public static class HttpUtils {

public static Task<Result<R, HttpError>> DoRequest<T, U, R>(
IPluginLog log,
HttpClient client,
string baseUrl,
T requestObject,
Func<HttpClient, HttpContent, Task<HttpResponseMessage>> requestAction,
Func<HttpContent, Task<HttpResponseMessage>> requestAction,
Func<U, R> responseTransform
) =>
DoRequest(log, client, baseUrl, requestObject, requestAction)
DoRequest(log, requestObject, requestAction)
.Then(
result => result.Bind<string, R, HttpError>(
responseJson => Utils.Try(
Expand All @@ -36,20 +34,15 @@ Func<U, R> responseTransform

public static async Task<Result<string, HttpError>> DoRequest<T>(
IPluginLog log,
HttpClient client,
string baseUrl,
T requestObject,
Func<HttpClient, HttpContent, Task<HttpResponseMessage>> requestAction
Func<HttpContent, Task<HttpResponseMessage>> requestAction
) {
try {
var requestPayload = JsonConvert.SerializeObject(requestObject, JsonSerializerSettings);
log.Debug("Request body: {0:l}", requestPayload);
var requestContent = new StringContent(requestPayload, Encoding.UTF8, Constants.MediaTypeJson);

client.BaseAddress = new Uri(baseUrl);
client.DefaultRequestHeaders.UserAgent.Add(Constants.UserAgent);
client.DefaultRequestHeaders.Accept.Add(Constants.MediaTypeJson);
var response = await requestAction(client, requestContent);
var response = await requestAction(requestContent);
log.Debug(
"Request: {0:l}\n\nResponse: {1:l}",
response.RequestMessage!.ToString(),
Expand Down
2 changes: 2 additions & 0 deletions ScoutHelper/Utils/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,7 @@ private static IEnumerable<string> Tokenize(string s) {
public static bool ActualValuesEqualBecauseMicrosoftHasBrainDamage(object? objA, object? objB) =>
Equals(objA, objB) || Equals(JsonConvert.SerializeObject(objA), JsonConvert.SerializeObject(objB));

public static Uri AsUri(this string str) => new(str);

#endregion
}

0 comments on commit 448c760

Please sign in to comment.