diff --git a/src/Tgstation.Server.Client/ApiClient.cs b/src/Tgstation.Server.Client/ApiClient.cs index e2d7aab334..7721de3138 100644 --- a/src/Tgstation.Server.Client/ApiClient.cs +++ b/src/Tgstation.Server.Client/ApiClient.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; @@ -27,10 +28,15 @@ namespace Tgstation.Server.Client } /// - /// The for the + /// The for the /// readonly HttpClient httpClient; + /// + /// The s used by the + /// + readonly List requestLoggers; + /// /// Construct an /// @@ -42,6 +48,7 @@ namespace Tgstation.Server.Client Headers = apiHeaders ?? throw new ArgumentNullException(nameof(apiHeaders)); httpClient = new HttpClient(); + requestLoggers = new List(); } /// @@ -67,29 +74,18 @@ namespace Tgstation.Server.Client var fullUri = new Uri(Url, route); - HttpContent content = null; + var message = new HttpRequestMessage(method, fullUri); + if (body != null) - content = new StringContent(JsonConvert.SerializeObject(body)); + message.Content = new StringContent(JsonConvert.SerializeObject(body)); - Task task; - lock (this) - { - httpClient.DefaultRequestHeaders.Clear(); - Headers.SetRequestHeaders(httpClient.DefaultRequestHeaders, instanceId); + Headers.SetRequestHeaders(message.Headers, instanceId); - if (method == HttpMethod.Get) - task = httpClient.GetAsync(route); - else if (method == HttpMethod.Put) - task = httpClient.PutAsync(fullUri, content, cancellationToken); - else if (method == HttpMethod.Post) - task = httpClient.PostAsync(fullUri, content, cancellationToken); - else if (method == HttpMethod.Delete) - task = httpClient.DeleteAsync(fullUri, cancellationToken); - else - throw new NotSupportedException(); - } + await Task.WhenAll(requestLoggers.Select(x => x.LogRequest(message, cancellationToken))).ConfigureAwait(false); - var response = await task.ConfigureAwait(false); + var response = await httpClient.SendAsync(message, cancellationToken).ConfigureAwait(false); + + await Task.WhenAll(requestLoggers.Select(x => x.LogResponse(response, cancellationToken))).ConfigureAwait(false); var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); @@ -173,5 +169,8 @@ namespace Tgstation.Server.Client /// public Task Create(string route, long instanceId, CancellationToken cancellationToken) => RunRequest(route, new object(), HttpMethod.Put, instanceId, cancellationToken); + + /// + public void AddRequestLogger(IRequestLogger requestLogger) => requestLoggers.Add(requestLogger ?? throw new ArgumentNullException(nameof(requestLogger))); } } \ No newline at end of file diff --git a/src/Tgstation.Server.Client/IApiClient.cs b/src/Tgstation.Server.Client/IApiClient.cs index e2a4346396..acf5fdbf0a 100644 --- a/src/Tgstation.Server.Client/IApiClient.cs +++ b/src/Tgstation.Server.Client/IApiClient.cs @@ -16,6 +16,12 @@ namespace Tgstation.Server.Client TimeSpan Timeout { get; set; } + /// + /// Adds a to the request pipeline + /// + /// The to add + void AddRequestLogger(IRequestLogger requestLogger); + Task Create(string route, TBody body, CancellationToken cancellationToken); Task Create(string route, CancellationToken cancellationToken); Task Read(string route, CancellationToken cancellationToken); diff --git a/src/Tgstation.Server.Client/IRequestLogger.cs b/src/Tgstation.Server.Client/IRequestLogger.cs new file mode 100644 index 0000000000..6115d283ca --- /dev/null +++ b/src/Tgstation.Server.Client/IRequestLogger.cs @@ -0,0 +1,29 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Tgstation.Server.Client +{ + /// + /// For logging HTTP requests and responses + /// + public interface IRequestLogger + { + /// + /// Log a request + /// + /// The representing the request + /// The for the operation + /// A representing the running operation + Task LogRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken); + + /// + /// Log a response + /// + /// The representing the request + /// The for the operation + /// A representing the running operation + Task LogResponse(HttpResponseMessage responseMessage, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/src/Tgstation.Server.Client/IServerClient.cs b/src/Tgstation.Server.Client/IServerClient.cs index 3fa1d13666..3bd57d287e 100644 --- a/src/Tgstation.Server.Client/IServerClient.cs +++ b/src/Tgstation.Server.Client/IServerClient.cs @@ -39,5 +39,11 @@ namespace Tgstation.Server.Client /// The of the /// Task Version(CancellationToken cancellationToken); + + /// + /// Adds a to the request pipeline + /// + /// The to add + void AddRequestLogger(IRequestLogger requestLogger); } } diff --git a/src/Tgstation.Server.Client/ServerClient.cs b/src/Tgstation.Server.Client/ServerClient.cs index a592c3630d..7e34062840 100644 --- a/src/Tgstation.Server.Client/ServerClient.cs +++ b/src/Tgstation.Server.Client/ServerClient.cs @@ -53,7 +53,11 @@ namespace Tgstation.Server.Client /// public void Dispose() => apiClient.Dispose(); + /// public Task Version(CancellationToken cancellationToken) => apiClient.Read(Routes.Root, cancellationToken); + + /// + public void AddRequestLogger(IRequestLogger requestLogger) => apiClient.AddRequestLogger(requestLogger); } } \ No newline at end of file