diff --git a/build/Version.props b/build/Version.props
index 7559b69bfb..b3b449c726 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -7,7 +7,7 @@
4.5.0
9.9.0
10.3.0
- 11.3.0
+ 11.3.1
6.4.2
5.6.0
1.2.2
diff --git a/src/Tgstation.Server.Client/ApiClient.cs b/src/Tgstation.Server.Client/ApiClient.cs
index a01db4e9d8..cfb7795d98 100644
--- a/src/Tgstation.Server.Client/ApiClient.cs
+++ b/src/Tgstation.Server.Client/ApiClient.cs
@@ -20,6 +20,7 @@ using Newtonsoft.Json.Serialization;
using Tgstation.Server.Api;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Response;
+using Tgstation.Server.Common;
namespace Tgstation.Server.Client
{
@@ -50,7 +51,7 @@ namespace Tgstation.Server.Client
}
///
- /// The for the .
+ /// The for the .
///
readonly IHttpClient httpClient;
diff --git a/src/Tgstation.Server.Client/ApiClientFactory.cs b/src/Tgstation.Server.Client/ApiClientFactory.cs
index b003cb39c6..0e20eb3b00 100644
--- a/src/Tgstation.Server.Client/ApiClientFactory.cs
+++ b/src/Tgstation.Server.Client/ApiClientFactory.cs
@@ -1,6 +1,7 @@
using System;
using Tgstation.Server.Api;
+using Tgstation.Server.Common;
namespace Tgstation.Server.Client
{
@@ -13,7 +14,7 @@ namespace Tgstation.Server.Client
ApiHeaders apiHeaders,
ApiHeaders? tokenRefreshHeaders,
bool authless) => new ApiClient(
- new HttpClientImplementation(),
+ new HttpClient(),
url,
apiHeaders,
tokenRefreshHeaders,
diff --git a/src/Tgstation.Server.Client/HttpClientImplementation.cs b/src/Tgstation.Server.Client/HttpClientImplementation.cs
deleted file mode 100644
index d27708df2a..0000000000
--- a/src/Tgstation.Server.Client/HttpClientImplementation.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Tgstation.Server.Client
-{
- ///
- sealed class HttpClientImplementation : IHttpClient
- {
- ///
- public TimeSpan Timeout
- {
- get => httpClient.Timeout;
- set => httpClient.Timeout = value;
- }
-
- ///
- /// The real .
- ///
- readonly HttpClient httpClient;
-
- ///
- /// Initializes a new instance of the class.
- ///
- public HttpClientImplementation()
- {
- httpClient = new HttpClient();
- }
-
- ///
- public void Dispose() => httpClient.Dispose();
-
- ///
- public Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
- }
-}
diff --git a/src/Tgstation.Server.Client/Tgstation.Server.Client.csproj b/src/Tgstation.Server.Client/Tgstation.Server.Client.csproj
index 9abd30240d..e2272b2855 100644
--- a/src/Tgstation.Server.Client/Tgstation.Server.Client.csproj
+++ b/src/Tgstation.Server.Client/Tgstation.Server.Client.csproj
@@ -41,6 +41,7 @@
+
diff --git a/src/Tgstation.Server.Common/HttpClient.cs b/src/Tgstation.Server.Common/HttpClient.cs
new file mode 100644
index 0000000000..41dcf6dec4
--- /dev/null
+++ b/src/Tgstation.Server.Common/HttpClient.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Tgstation.Server.Common
+{
+ ///
+ public sealed class HttpClient : IHttpClient
+ {
+ ///
+ public TimeSpan Timeout
+ {
+ get => httpClient.Timeout;
+ set => httpClient.Timeout = value;
+ }
+
+ ///
+ public HttpRequestHeaders DefaultRequestHeaders => httpClient.DefaultRequestHeaders;
+
+ ///
+ /// The real .
+ ///
+ readonly System.Net.Http.HttpClient httpClient;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The to wrap.
+ public HttpClient(System.Net.Http.HttpClient implementation)
+ {
+ httpClient = implementation ?? throw new ArgumentNullException(nameof(implementation));
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public HttpClient()
+ : this(new System.Net.Http.HttpClient())
+ {
+ }
+
+ ///
+ public void Dispose() => httpClient.Dispose();
+
+ ///
+ public Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
+ }
+}
diff --git a/src/Tgstation.Server.Client/IHttpClient.cs b/src/Tgstation.Server.Common/IHttpClient.cs
similarity index 73%
rename from src/Tgstation.Server.Client/IHttpClient.cs
rename to src/Tgstation.Server.Common/IHttpClient.cs
index e7e5ad5325..a1ce0190e0 100644
--- a/src/Tgstation.Server.Client/IHttpClient.cs
+++ b/src/Tgstation.Server.Common/IHttpClient.cs
@@ -1,20 +1,26 @@
using System;
using System.Net.Http;
+using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
-namespace Tgstation.Server.Client
+namespace Tgstation.Server.Common
{
///
/// For sending HTTP requests.
///
- interface IHttpClient : IDisposable
+ public interface IHttpClient : IDisposable
{
///
/// The request timeout.
///
TimeSpan Timeout { get; set; }
+ ///
+ /// The used on every request.
+ ///
+ HttpRequestHeaders DefaultRequestHeaders { get; }
+
///
/// Send an HTTP request.
///
diff --git a/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj b/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj
new file mode 100644
index 0000000000..748bb6ebb3
--- /dev/null
+++ b/src/Tgstation.Server.Common/Tgstation.Server.Common.csproj
@@ -0,0 +1,31 @@
+
+
+
+
+ netstandard2.0
+ Full
+ $(TgsCoreVersion)
+ ../../build/analyzers.ruleset
+ latest
+ enable
+ bin\$(Configuration)\netstandard2.0\Tgstation.Server.Client.xml
+ true
+
+
+
+ true
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
diff --git a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
index 67e80cda1f..0b26625bc7 100644
--- a/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/ByondInstallerBase.cs
@@ -39,14 +39,21 @@ namespace Tgstation.Server.Host.Components.Byond
///
protected ILogger Logger { get; }
+ ///
+ /// The for the .
+ ///
+ readonly IFileDownloader fileDownloader;
+
///
/// Initializes a new instance of the class.
///
/// The value of .
+ /// The value of .
/// The value of .
- protected ByondInstallerBase(IIOManager ioManager, ILogger logger)
+ protected ByondInstallerBase(IIOManager ioManager, IFileDownloader fileDownloader, ILogger logger)
{
IOManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
+ this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
@@ -88,11 +95,9 @@ namespace Tgstation.Server.Host.Components.Byond
if (version == null)
throw new ArgumentNullException(nameof(version));
+ Logger.LogTrace("Downloading BYOND version {major}.{minor}...", version.Major, version.Minor);
var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsUrlTemplate, version.Major, version.Minor);
-
- Logger.LogTrace("Downloading from: {0}", url);
-
- return IOManager.DownloadFile(new Uri(url), cancellationToken);
+ return fileDownloader.DownloadFile(new Uri(url), cancellationToken);
}
}
}
diff --git a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
index 876ed37aa7..ddd012ab0c 100644
--- a/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs
@@ -49,9 +49,14 @@ namespace Tgstation.Server.Host.Components.Byond
///
/// The value of .
/// The for the .
+ /// The for the .
/// The for the .
- public PosixByondInstaller(IPostWriteHandler postWriteHandler, IIOManager ioManager, ILogger logger)
- : base(ioManager, logger)
+ public PosixByondInstaller(
+ IPostWriteHandler postWriteHandler,
+ IIOManager ioManager,
+ IFileDownloader fileDownloader,
+ ILogger logger)
+ : base(ioManager, fileDownloader, logger)
{
this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
@@ -89,7 +94,7 @@ namespace Tgstation.Server.Host.Components.Byond
async Task WriteAndMakeExecutable(string pathToScript, string script)
{
- Logger.LogTrace("Writing script {0}:{1}{2}", pathToScript, Environment.NewLine, script);
+ Logger.LogTrace("Writing script {path}:{newLine}{scriptContents}", pathToScript, Environment.NewLine, script);
await IOManager.WriteAllBytes(pathToScript, Encoding.ASCII.GetBytes(script), cancellationToken);
postWriteHandler.HandleWrite(IOManager.ResolvePath(pathToScript));
}
diff --git a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
index 76d47e26f6..bb999f2e89 100644
--- a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
@@ -81,9 +81,15 @@ namespace Tgstation.Server.Host.Components.Byond
/// The value of .
/// The containing the value of .
/// The for the .
+ /// The for the .
/// The for the .
- public WindowsByondInstaller(IProcessExecutor processExecutor, IIOManager ioManager, IOptions generalConfigurationOptions, ILogger logger)
- : base(ioManager, logger)
+ public WindowsByondInstaller(
+ IProcessExecutor processExecutor,
+ IIOManager ioManager,
+ IFileDownloader fileDownloader,
+ IOptions generalConfigurationOptions,
+ ILogger logger)
+ : base(ioManager, fileDownloader, logger)
{
this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
diff --git a/src/Tgstation.Server.Host/Core/AbstractHttpClientFactory.cs b/src/Tgstation.Server.Host/Core/AbstractHttpClientFactory.cs
new file mode 100644
index 0000000000..c471bb937a
--- /dev/null
+++ b/src/Tgstation.Server.Host/Core/AbstractHttpClientFactory.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Net.Http;
+
+using Microsoft.Extensions.Logging;
+
+using Tgstation.Server.Common;
+using Tgstation.Server.Host.System;
+
+namespace Tgstation.Server.Host.Core
+{
+ ///
+ sealed class AbstractHttpClientFactory : IAbstractHttpClientFactory
+ {
+ ///
+ /// The real .
+ ///
+ readonly IHttpClientFactory httpClientFactory;
+
+ ///
+ /// The for the .
+ ///
+ readonly IAssemblyInformationProvider assemblyInformationProvider;
+
+ ///
+ /// The for the .
+ ///
+ readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of .
+ /// The value of .
+ /// The value of .
+ public AbstractHttpClientFactory(
+ IHttpClientFactory httpClientFactory,
+ IAssemblyInformationProvider assemblyInformationProvider,
+ ILogger logger)
+ {
+ this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
+ this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
+ this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ ///
+ public IHttpClient CreateClient()
+ {
+ logger.LogTrace("Creating client...");
+ var innerClient = httpClientFactory.CreateClient();
+ try
+ {
+ var client = new Tgstation.Server.Common.HttpClient(innerClient);
+ client.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
+ return client;
+ }
+ catch
+ {
+ innerClient.Dispose();
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs
index e83fb92f81..33a3cd3ed2 100644
--- a/src/Tgstation.Server.Host/Core/Application.cs
+++ b/src/Tgstation.Server.Host/Core/Application.cs
@@ -73,7 +73,7 @@ namespace Tgstation.Server.Host.Core
public static IServerFactory CreateDefaultServerFactory()
{
var assemblyInformationProvider = new AssemblyInformationProvider();
- var ioManager = new DefaultIOManager(assemblyInformationProvider);
+ var ioManager = new DefaultIOManager();
return new ServerFactory(
assemblyInformationProvider,
ioManager);
@@ -253,6 +253,7 @@ namespace Tgstation.Server.Host.Core
// Enable managed HTTP clients
services.AddHttpClient();
+ services.AddSingleton();
void AddTypedContext() where TContext : DatabaseContext
{
@@ -350,6 +351,7 @@ namespace Tgstation.Server.Host.Core
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton(x => x.GetRequiredService());
services.AddSingleton(x => x.GetRequiredService());
diff --git a/src/Tgstation.Server.Host/Core/IAbstractHttpClientFactory.cs b/src/Tgstation.Server.Host/Core/IAbstractHttpClientFactory.cs
new file mode 100644
index 0000000000..d031fb350f
--- /dev/null
+++ b/src/Tgstation.Server.Host/Core/IAbstractHttpClientFactory.cs
@@ -0,0 +1,16 @@
+using Tgstation.Server.Common;
+
+namespace Tgstation.Server.Host.Core
+{
+ ///
+ /// Creates s.
+ ///
+ public interface IAbstractHttpClientFactory
+ {
+ ///
+ /// Create a .
+ ///
+ /// A new .
+ IHttpClient CreateClient();
+ }
+}
diff --git a/src/Tgstation.Server.Host/Core/ServerUpdater.cs b/src/Tgstation.Server.Host/Core/ServerUpdater.cs
index 4c1a99eb79..b8139202de 100644
--- a/src/Tgstation.Server.Host/Core/ServerUpdater.cs
+++ b/src/Tgstation.Server.Host/Core/ServerUpdater.cs
@@ -30,6 +30,11 @@ namespace Tgstation.Server.Host.Core
///
readonly IIOManager ioManager;
+ ///
+ /// The for the .
+ ///
+ readonly IFileDownloader fileDownloader;
+
///
/// The for the .
///
@@ -55,18 +60,21 @@ namespace Tgstation.Server.Host.Core
///
/// The value of .
/// The value of .
+ /// The value of .
/// The value of .
/// The value of .
/// The containing the value of .
public ServerUpdater(
IGitHubClientFactory gitHubClientFactory,
IIOManager ioManager,
+ IFileDownloader fileDownloader,
IServerControl serverControl,
ILogger logger,
IOptions updatesConfigurationOptions)
{
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
+ this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader));
this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions));
@@ -154,7 +162,7 @@ namespace Tgstation.Server.Host.Core
try
{
logger.LogTrace("Downloading zip package...");
- updateZipData = await ioManager.DownloadFile(serverUpdateOperation.UpdateZipUrl, cancellationToken);
+ updateZipData = await fileDownloader.DownloadFile(serverUpdateOperation.UpdateZipUrl, cancellationToken);
}
catch (Exception e1)
{
diff --git a/src/Tgstation.Server.Host/IO/DefaultIOManager.cs b/src/Tgstation.Server.Host/IO/DefaultIOManager.cs
index 7ad9ad7872..6edc397308 100644
--- a/src/Tgstation.Server.Host/IO/DefaultIOManager.cs
+++ b/src/Tgstation.Server.Host/IO/DefaultIOManager.cs
@@ -3,12 +3,10 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
-using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Host.Core;
-using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.IO
{
@@ -32,11 +30,6 @@ namespace Tgstation.Server.Host.IO
///
public const TaskCreationOptions BlockingTaskCreationOptions = TaskCreationOptions.None;
- ///
- /// The for the .
- ///
- readonly IAssemblyInformationProvider assemblyInformationProvider;
-
///
/// Recursively empty a directory.
///
@@ -67,22 +60,6 @@ namespace Tgstation.Server.Host.IO
dir.Delete(true);
}
- ///
- /// Initializes a new instance of the class.
- ///
- /// The value of .
- public DefaultIOManager(IAssemblyInformationProvider assemblyInformationProvider)
- {
- this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- protected DefaultIOManager()
- {
- }
-
///
public async Task CopyDirectory(
string src,
@@ -296,29 +273,6 @@ namespace Tgstation.Server.Host.IO
BlockingTaskCreationOptions,
TaskScheduler.Current);
- ///
- public async Task DownloadFile(Uri url, CancellationToken cancellationToken)
- {
- using var httpClient = new HttpClient();
- httpClient.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
- var webRequestTask = httpClient.GetAsync(url, cancellationToken);
- using var response = await webRequestTask;
- response.EnsureSuccessStatusCode();
- using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
- var memoryStream = new MemoryStream();
- try
- {
- await responseStream.CopyToAsync(memoryStream, cancellationToken);
- memoryStream.Seek(0, SeekOrigin.Begin);
- return memoryStream;
- }
- catch
- {
- memoryStream.Dispose();
- throw;
- }
- }
-
///
public Task ZipToDirectory(string path, Stream zipFile, CancellationToken cancellationToken) => Task.Factory.StartNew(
() =>
diff --git a/src/Tgstation.Server.Host/IO/FileDownloader.cs b/src/Tgstation.Server.Host/IO/FileDownloader.cs
new file mode 100644
index 0000000000..976f4d7ec7
--- /dev/null
+++ b/src/Tgstation.Server.Host/IO/FileDownloader.cs
@@ -0,0 +1,64 @@
+using System;
+using System.IO;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Microsoft.Extensions.Logging;
+
+using Tgstation.Server.Host.Core;
+
+namespace Tgstation.Server.Host.IO
+{
+ ///
+ public sealed class FileDownloader : IFileDownloader
+ {
+ ///
+ /// The for the .
+ ///
+ readonly IAbstractHttpClientFactory httpClientFactory;
+
+ ///
+ /// The for the .
+ ///
+ readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value of .
+ /// The value of .
+ public FileDownloader(IAbstractHttpClientFactory httpClientFactory, ILogger logger)
+ {
+ this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
+ this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ }
+
+ ///
+ public async Task DownloadFile(Uri url, CancellationToken cancellationToken)
+ {
+ logger.LogDebug("Starting download of {url}...", url);
+ using var httpClient = httpClientFactory.CreateClient();
+ using var request = new HttpRequestMessage(
+ HttpMethod.Get,
+ url);
+
+ var webRequestTask = httpClient.SendAsync(request, cancellationToken);
+ using var response = await webRequestTask;
+ response.EnsureSuccessStatusCode();
+ using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
+ var memoryStream = new MemoryStream();
+ try
+ {
+ await responseStream.CopyToAsync(memoryStream, cancellationToken);
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ return memoryStream;
+ }
+ catch
+ {
+ memoryStream.Dispose();
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/Tgstation.Server.Host/IO/IFileDownloader.cs b/src/Tgstation.Server.Host/IO/IFileDownloader.cs
new file mode 100644
index 0000000000..199d904f06
--- /dev/null
+++ b/src/Tgstation.Server.Host/IO/IFileDownloader.cs
@@ -0,0 +1,21 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Tgstation.Server.Host.IO
+{
+ ///
+ /// Downloads files.
+ ///
+ interface IFileDownloader
+ {
+ ///
+ /// Downloads a file from .
+ ///
+ /// The URL to download.
+ /// A for the operation.
+ /// A resulting in a of the downloaded file.
+ Task DownloadFile(Uri url, CancellationToken cancellationToken);
+ }
+}
diff --git a/src/Tgstation.Server.Host/IO/IIOManager.cs b/src/Tgstation.Server.Host/IO/IIOManager.cs
index a51d130720..f9275e1216 100644
--- a/src/Tgstation.Server.Host/IO/IIOManager.cs
+++ b/src/Tgstation.Server.Host/IO/IIOManager.cs
@@ -192,14 +192,6 @@ namespace Tgstation.Server.Host.IO
/// A representing the running operation.
Task MoveDirectory(string source, string destination, CancellationToken cancellationToken);
- ///
- /// Downloads a file from .
- ///
- /// The URL to download.
- /// A for the operation.
- /// A resulting in a of the downloaded file.
- Task DownloadFile(Uri url, CancellationToken cancellationToken);
-
///
/// Extract a set of to a given .
///
diff --git a/src/Tgstation.Server.Host/Security/OAuth/DiscordOAuthValidator.cs b/src/Tgstation.Server.Host/Security/OAuth/DiscordOAuthValidator.cs
index e74a6c9d4b..f147d20696 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/DiscordOAuthValidator.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/DiscordOAuthValidator.cs
@@ -1,11 +1,10 @@
using System;
-using System.Net.Http;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Configuration;
-using Tgstation.Server.Host.System;
+using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -18,29 +17,27 @@ namespace Tgstation.Server.Host.Security.OAuth
public override OAuthProvider Provider => OAuthProvider.Discord;
///
- protected override Uri TokenUrl => new Uri("https://discord.com/api/oauth2/token");
+ protected override Uri TokenUrl => new ("https://discord.com/api/oauth2/token");
///
- protected override Uri UserInformationUrl => new Uri("https://discord.com/api/users/@me");
+ protected override Uri UserInformationUrl => new ("https://discord.com/api/users/@me");
///
/// Initializes a new instance of the class.
///
- /// The for the .
- /// The for the .
+ /// The for the .
/// The for the .
/// The for the .
public DiscordOAuthValidator(
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILogger logger,
OAuthConfiguration oAuthConfiguration)
- : base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
+ : base(httpClientFactory, logger, oAuthConfiguration)
{
}
///
- protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "identify");
+ protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "identify");
///
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
diff --git a/src/Tgstation.Server.Host/Security/OAuth/GenericOAuthValidator.cs b/src/Tgstation.Server.Host/Security/OAuth/GenericOAuthValidator.cs
index f1cccb7437..a88003bb46 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/GenericOAuthValidator.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/GenericOAuthValidator.cs
@@ -13,8 +13,9 @@ using Newtonsoft.Json.Serialization;
using Tgstation.Server.Api;
using Tgstation.Server.Api.Models;
+using Tgstation.Server.Common;
using Tgstation.Server.Host.Configuration;
-using Tgstation.Server.Host.System;
+using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -49,18 +50,13 @@ namespace Tgstation.Server.Host.Security.OAuth
///
/// The for the .
///
- readonly IHttpClientFactory httpClientFactory;
-
- ///
- /// The for the .
- ///
- readonly IAssemblyInformationProvider assemblyInformationProvider;
+ readonly IAbstractHttpClientFactory httpClientFactory;
///
/// Gets that should be used.
///
/// A new .
- protected static JsonSerializerSettings SerializerSettings() => new JsonSerializerSettings
+ protected static JsonSerializerSettings SerializerSettings() => new ()
{
ContractResolver = new DefaultContractResolver
{
@@ -72,17 +68,14 @@ namespace Tgstation.Server.Host.Security.OAuth
/// Initializes a new instance of the class.
///
/// The value of .
- /// The value of .
/// The value of .
/// The value of .
public GenericOAuthValidator(
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILogger logger,
OAuthConfiguration oAuthConfiguration)
{
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
- this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
OAuthConfiguration = oAuthConfiguration ?? throw new ArgumentNullException(nameof(oAuthConfiguration));
}
@@ -109,7 +102,7 @@ namespace Tgstation.Server.Host.Security.OAuth
tokenRequest.Content = new FormUrlEncodedContent(tokenRequestDictionary);
var tokenResponse = await httpClient.SendAsync(tokenRequest, cancellationToken);
- tokenResponsePayload = await tokenResponse.Content.ReadAsStringAsync();
+ tokenResponsePayload = await tokenResponse.Content.ReadAsStringAsync(cancellationToken);
tokenResponse.EnsureSuccessStatusCode();
var tokenResponseJson = JObject.Parse(tokenResponsePayload);
@@ -129,7 +122,7 @@ namespace Tgstation.Server.Host.Security.OAuth
accessToken);
var userInformationResponse = await httpClient.SendAsync(userInformationRequest, cancellationToken);
- userInformationPayload = await userInformationResponse.Content.ReadAsStringAsync();
+ userInformationPayload = await userInformationResponse.Content.ReadAsStringAsync(cancellationToken);
userInformationResponse.EnsureSuccessStatusCode();
var userInformationJson = JObject.Parse(userInformationPayload);
@@ -178,16 +171,15 @@ namespace Tgstation.Server.Host.Security.OAuth
protected abstract OAuthTokenRequest CreateTokenRequest(string code);
///
- /// Create a new configured .
+ /// Create a new configured .
///
- /// A new configured .
- HttpClient CreateHttpClient()
+ /// A new configured .
+ IHttpClient CreateHttpClient()
{
var httpClient = httpClientFactory.CreateClient();
try
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
- httpClient.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
return httpClient;
}
catch
diff --git a/src/Tgstation.Server.Host/Security/OAuth/InvisionCommunityOAuthValidator.cs b/src/Tgstation.Server.Host/Security/OAuth/InvisionCommunityOAuthValidator.cs
index e0021d0143..d310e026f4 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/InvisionCommunityOAuthValidator.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/InvisionCommunityOAuthValidator.cs
@@ -1,11 +1,10 @@
using System;
-using System.Net.Http;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Configuration;
-using Tgstation.Server.Host.System;
+using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -18,29 +17,27 @@ namespace Tgstation.Server.Host.Security.OAuth
public override OAuthProvider Provider => OAuthProvider.InvisionCommunity;
///
- protected override Uri TokenUrl => new Uri($"{OAuthConfiguration.ServerUrl}/oauth/token/"); // This needs the trailing slash or it doesnt get the token. Do not remove.
+ protected override Uri TokenUrl => new ($"{OAuthConfiguration.ServerUrl}/oauth/token/"); // This needs the trailing slash or it doesnt get the token. Do not remove.
///
- protected override Uri UserInformationUrl => new Uri($"{OAuthConfiguration.ServerUrl}/api/core/me");
+ protected override Uri UserInformationUrl => new ($"{OAuthConfiguration.ServerUrl}/api/core/me");
///
/// Initializes a new instance of the class.
///
- /// The for the .
- /// The for the .
+ /// The for the .
/// The for the .
/// The for the .
public InvisionCommunityOAuthValidator(
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILogger logger,
OAuthConfiguration oAuthConfiguration)
- : base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
+ : base(httpClientFactory, logger, oAuthConfiguration)
{
}
///
- protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "profile");
+ protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "profile");
///
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
diff --git a/src/Tgstation.Server.Host/Security/OAuth/KeycloakOAuthValidator.cs b/src/Tgstation.Server.Host/Security/OAuth/KeycloakOAuthValidator.cs
index 87e3cdbce8..6d168aa471 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/KeycloakOAuthValidator.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/KeycloakOAuthValidator.cs
@@ -1,11 +1,10 @@
using System;
-using System.Net.Http;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Configuration;
-using Tgstation.Server.Host.System;
+using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -18,10 +17,10 @@ namespace Tgstation.Server.Host.Security.OAuth
public override OAuthProvider Provider => OAuthProvider.Keycloak;
///
- protected override Uri TokenUrl => new Uri($"{BaseProtocolPath}/token");
+ protected override Uri TokenUrl => new ($"{BaseProtocolPath}/token");
///
- protected override Uri UserInformationUrl => new Uri($"{BaseProtocolPath}/userinfo");
+ protected override Uri UserInformationUrl => new ($"{BaseProtocolPath}/userinfo");
///
/// Base path to the server's OAuth endpoint.
@@ -31,21 +30,19 @@ namespace Tgstation.Server.Host.Security.OAuth
///
/// Initializes a new instance of the class.
///
- /// The for the .
- /// The for the .
+ /// The for the .
/// The for the .
/// The for the .
public KeycloakOAuthValidator(
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILogger logger,
OAuthConfiguration oAuthConfiguration)
- : base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
+ : base(httpClientFactory, logger, oAuthConfiguration)
{
}
///
- protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "openid");
+ protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "openid");
///
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
diff --git a/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs b/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs
index 6f92824239..298d9b25e1 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/OAuthProviders.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@@ -11,7 +10,6 @@ using Microsoft.Extensions.Options;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
-using Tgstation.Server.Host.System;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -27,14 +25,12 @@ namespace Tgstation.Server.Host.Security.OAuth
/// Initializes a new instance of the class.
///
/// The to use.
- /// The to use.
- /// The to use.
+ /// The to use.
/// The to use.
/// The containing the to use.
public OAuthProviders(
IGitHubClientFactory gitHubClientFactory,
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILoggerFactory loggerFactory,
IOptions securityConfigurationOptions)
{
@@ -60,7 +56,6 @@ namespace Tgstation.Server.Host.Security.OAuth
validatorsBuilder.Add(
new DiscordOAuthValidator(
httpClientFactory,
- assemblyInformationProvider,
loggerFactory.CreateLogger(),
discordConfig));
@@ -68,7 +63,6 @@ namespace Tgstation.Server.Host.Security.OAuth
validatorsBuilder.Add(
new TGForumsOAuthValidator(
httpClientFactory,
- assemblyInformationProvider,
loggerFactory.CreateLogger(),
tgConfig));
@@ -76,7 +70,6 @@ namespace Tgstation.Server.Host.Security.OAuth
validatorsBuilder.Add(
new KeycloakOAuthValidator(
httpClientFactory,
- assemblyInformationProvider,
loggerFactory.CreateLogger(),
keyCloakConfig));
@@ -84,7 +77,6 @@ namespace Tgstation.Server.Host.Security.OAuth
validatorsBuilder.Add(
new InvisionCommunityOAuthValidator(
httpClientFactory,
- assemblyInformationProvider,
loggerFactory.CreateLogger(),
invisionConfig));
}
diff --git a/src/Tgstation.Server.Host/Security/OAuth/TGForumsOAuthValidator.cs b/src/Tgstation.Server.Host/Security/OAuth/TGForumsOAuthValidator.cs
index 3c0f504986..91d21a5291 100644
--- a/src/Tgstation.Server.Host/Security/OAuth/TGForumsOAuthValidator.cs
+++ b/src/Tgstation.Server.Host/Security/OAuth/TGForumsOAuthValidator.cs
@@ -1,11 +1,10 @@
using System;
-using System.Net.Http;
using Microsoft.Extensions.Logging;
using Tgstation.Server.Api.Models;
using Tgstation.Server.Host.Configuration;
-using Tgstation.Server.Host.System;
+using Tgstation.Server.Host.Core;
namespace Tgstation.Server.Host.Security.OAuth
{
@@ -26,18 +25,15 @@ namespace Tgstation.Server.Host.Security.OAuth
///
/// Initializes a new instance of the class.
///
- /// The for the .
- /// The for the .
+ /// The for the .
/// The for the .
/// The for the .
public TGForumsOAuthValidator(
- IHttpClientFactory httpClientFactory,
- IAssemblyInformationProvider assemblyInformationProvider,
+ IAbstractHttpClientFactory httpClientFactory,
ILogger logger,
OAuthConfiguration oAuthConfiguration)
: base(
httpClientFactory,
- assemblyInformationProvider,
logger,
oAuthConfiguration)
{
diff --git a/src/Tgstation.Server.Host/Swarm/SwarmService.cs b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
index f967e85726..51ecf82811 100644
--- a/src/Tgstation.Server.Host/Swarm/SwarmService.cs
+++ b/src/Tgstation.Server.Host/Swarm/SwarmService.cs
@@ -71,11 +71,6 @@ namespace Tgstation.Server.Host.Swarm
///
bool SwarmMode => swarmConfiguration.PrivateKey != null;
- ///
- /// Lazily constructed .
- ///
- readonly Lazy lazyRestartRegistration;
-
///
/// The for the .
///
@@ -92,9 +87,9 @@ namespace Tgstation.Server.Host.Swarm
readonly IAssemblyInformationProvider assemblyInformationProvider;
///
- /// The for the .
+ /// The for the .
///
- readonly IHttpClientFactory httpClientFactory;
+ readonly IAbstractHttpClientFactory httpClientFactory;
///
/// The for the .
@@ -106,6 +101,11 @@ namespace Tgstation.Server.Host.Swarm
///
readonly IServerUpdater serverUpdater;
+ ///
+ /// The for the .
+ ///
+ readonly IRestartRegistration restartRegistration;
+
///
/// The for the .
///
@@ -202,7 +202,7 @@ namespace Tgstation.Server.Host.Swarm
IDatabaseContextFactory databaseContextFactory,
IDatabaseSeeder databaseSeeder,
IAssemblyInformationProvider assemblyInformationProvider,
- IHttpClientFactory httpClientFactory,
+ IAbstractHttpClientFactory httpClientFactory,
IServerControl serverControl,
IServerUpdater serverUpdater,
IAsyncDelayer asyncDelayer,
@@ -215,6 +215,7 @@ namespace Tgstation.Server.Host.Swarm
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
if (serverControl == null)
throw new ArgumentNullException(nameof(serverControl));
+ restartRegistration = serverControl.RegisterForRestart(this);
this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
@@ -249,12 +250,14 @@ namespace Tgstation.Server.Host.Swarm
updateSynchronizationLock = new object();
}
-
- lazyRestartRegistration = new Lazy(() => serverControl.RegisterForRestart(this));
}
///
- public void Dispose() => serverHealthCheckCancellationTokenSource?.Dispose();
+ public void Dispose()
+ {
+ restartRegistration.Dispose();
+ serverHealthCheckCancellationTokenSource?.Dispose();
+ }
///
public async Task RemoteAbortUpdate(CancellationToken cancellationToken)
@@ -379,7 +382,7 @@ namespace Tgstation.Server.Host.Swarm
if (!commitGoAhead)
{
logger.LogDebug(
- "Update commit failed!{0}",
+ "Update commit failed!{maybeTimeout}",
timeoutTask.IsCompleted
? " Timed out!"
: String.Empty);
@@ -465,8 +468,6 @@ namespace Tgstation.Server.Host.Swarm
else
logger.LogTrace("Swarm mode disabled");
- _ = lazyRestartRegistration.Value;
-
SwarmRegistrationResult result;
if (swarmController)
{
@@ -1164,25 +1165,22 @@ namespace Tgstation.Server.Host.Swarm
var request = new HttpRequestMessage(
httpMethod,
swarmServer.Address + subroute[1..]);
-
- request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfiguration.PrivateKey);
- request.Headers.UserAgent.Clear();
- request.Headers.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
- request.Headers.Accept.Clear();
- request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
- if (registrationIdOverride.HasValue)
- request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationIdOverride.Value.ToString());
- else if (swarmController)
- {
- lock (swarmServers)
- if (registrationIds.TryGetValue(swarmServer.Identifier, out var registrationId))
- request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationId.ToString());
- }
- else if (controllerRegistration.HasValue)
- request.Headers.Add(SwarmConstants.RegistrationIdHeader, controllerRegistration.Value.ToString());
-
try
{
+ request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfiguration.PrivateKey);
+ request.Headers.Accept.Clear();
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
+ if (registrationIdOverride.HasValue)
+ request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationIdOverride.Value.ToString());
+ else if (swarmController)
+ {
+ lock (swarmServers)
+ if (registrationIds.TryGetValue(swarmServer.Identifier, out var registrationId))
+ request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationId.ToString());
+ }
+ else if (controllerRegistration.HasValue)
+ request.Headers.Add(SwarmConstants.RegistrationIdHeader, controllerRegistration.Value.ToString());
+
if (body != null)
request.Content = new StringContent(
JsonConvert.SerializeObject(body, SerializerSettings),
diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
index f342b53791..0730a00c27 100644
--- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
+++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
@@ -139,6 +139,7 @@
+
diff --git a/tests/Tgstation.Server.Client.Tests/TestApiClient.cs b/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
index 17b0919ccb..49ab83e74a 100644
--- a/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
+++ b/tests/Tgstation.Server.Client.Tests/TestApiClient.cs
@@ -11,8 +11,8 @@ using System.Threading;
using System.Threading.Tasks;
using Tgstation.Server.Api;
-using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Response;
+using Tgstation.Server.Common;
namespace Tgstation.Server.Client.Tests
{
diff --git a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
index 558ccf0faf..a78b19a86e 100644
--- a/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
+++ b/tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs
@@ -15,14 +15,16 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
[TestMethod]
public void TestConstruction()
{
- Assert.ThrowsException(() => new PosixByondInstaller(null, null, null));
+ Assert.ThrowsException(() => new PosixByondInstaller(null, null, null, null));
var mockPostWriteHandler = new Mock();
- Assert.ThrowsException(() => new PosixByondInstaller(mockPostWriteHandler.Object, null, null));
+ Assert.ThrowsException(() => new PosixByondInstaller(mockPostWriteHandler.Object, null, null, null));
var mockIOManager = new Mock();
- Assert.ThrowsException(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, null));
+ Assert.ThrowsException(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, null, null));
+ var mockFileDownloader = Mock.Of();
+ Assert.ThrowsException(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, null));
var mockLogger = new Mock>();
- _ = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
+ _ = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
}
[TestMethod]
@@ -31,7 +33,8 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
var mockPostWriteHandler = new Mock();
var mockIOManager = new Mock();
var mockLogger = new Mock>();
- var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
+ var mockFileDownloader = Mock.Of();
+ var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
await installer.CleanCache(default);
}
@@ -42,12 +45,13 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
var mockIOManager = new Mock();
var mockPostWriteHandler = new Mock();
var mockLogger = new Mock>();
- var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
+ var mockFileDownloader = new Mock();
+ var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader.Object, mockLogger.Object);
await Assert.ThrowsExceptionAsync(() => installer.DownloadVersion(null, default));
var ourArray = Array.Empty();
- mockIOManager.Setup(x => x.DownloadFile(It.Is(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(new MemoryStream(ourArray))).Verifiable();
+ mockFileDownloader.Setup(x => x.DownloadFile(It.Is(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(new MemoryStream(ourArray))).Verifiable();
var result = await installer.DownloadVersion(new Version(511, 1385), default);
@@ -61,7 +65,8 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
var mockIOManager = new Mock();
var mockPostWriteHandler = new Mock();
var mockLogger = new Mock>();
- var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
+ var mockFileDownloader = Mock.Of();
+ var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
const string FakePath = "fake";
await Assert.ThrowsExceptionAsync(() => installer.InstallByond(null, null, default));
diff --git a/tests/Tgstation.Server.Host.Tests/IO/TestIOManager.cs b/tests/Tgstation.Server.Host.Tests/IO/TestIOManager.cs
index d18400d728..d4a486b584 100644
--- a/tests/Tgstation.Server.Host.Tests/IO/TestIOManager.cs
+++ b/tests/Tgstation.Server.Host.Tests/IO/TestIOManager.cs
@@ -10,7 +10,7 @@ namespace Tgstation.Server.Host.IO.Tests
[TestClass]
public sealed class TestIOManager
{
- readonly IIOManager ioManager = new DefaultIOManager(new AssemblyInformationProvider());
+ readonly IIOManager ioManager = new DefaultIOManager();
[TestMethod]
public async Task TestDeleteDirectory()
diff --git a/tests/Tgstation.Server.Host.Tests/System/TestPosixSignalHandler.cs b/tests/Tgstation.Server.Host.Tests/System/TestPosixSignalHandler.cs
index 382e060f72..52c6129ef9 100644
--- a/tests/Tgstation.Server.Host.Tests/System/TestPosixSignalHandler.cs
+++ b/tests/Tgstation.Server.Host.Tests/System/TestPosixSignalHandler.cs
@@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.System.Tests
processExecutor = new ProcessExecutor(
new PosixProcessFeatures(
new Lazy(() => processExecutor),
- new DefaultIOManager(new AssemblyInformationProvider()),
+ new DefaultIOManager(),
loggerFactory.CreateLogger()),
Mock.Of(),
loggerFactory.CreateLogger(),
diff --git a/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs b/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs
index ae205ffaec..f6f680c50d 100644
--- a/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs
+++ b/tests/Tgstation.Server.Host.Tests/System/TestProcessFeatures.cs
@@ -22,7 +22,7 @@ namespace Tgstation.Server.Host.System.Tests
{
features = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? (IProcessFeatures)new WindowsProcessFeatures(Mock.Of>())
- : new PosixProcessFeatures(new Lazy(() => null), new DefaultIOManager(new AssemblyInformationProvider()), Mock.Of>());
+ : new PosixProcessFeatures(new Lazy(() => null), new DefaultIOManager(), Mock.Of>());
}
[TestMethod]
diff --git a/tests/Tgstation.Server.Host.Tests/TestProgram.cs b/tests/Tgstation.Server.Host.Tests/TestProgram.cs
index cb070dac63..67c3546d0c 100644
--- a/tests/Tgstation.Server.Host.Tests/TestProgram.cs
+++ b/tests/Tgstation.Server.Host.Tests/TestProgram.cs
@@ -84,7 +84,7 @@ namespace Tgstation.Server.Host.Tests
mockServer.Setup(x => x.Run(It.IsAny())).Throws(exception);
mockServer.SetupGet(x => x.RestartRequested).Returns(true);
var mockServerFactory = new Mock();
- mockServerFactory.SetupGet(x => x.IOManager).Returns(new DefaultIOManager(new AssemblyInformationProvider()));
+ mockServerFactory.SetupGet(x => x.IOManager).Returns(new DefaultIOManager());
mockServerFactory.Setup(x => x.CreateServer(It.IsNotNull(), It.IsAny(), It.IsAny())).ReturnsAsync(mockServer.Object);
var program = new Program
{
diff --git a/tests/Tgstation.Server.Tests/ConcreteHttpClientFactory.cs b/tests/Tgstation.Server.Tests/ConcreteHttpClientFactory.cs
new file mode 100644
index 0000000000..572c860b27
--- /dev/null
+++ b/tests/Tgstation.Server.Tests/ConcreteHttpClientFactory.cs
@@ -0,0 +1,10 @@
+using Tgstation.Server.Common;
+using Tgstation.Server.Host.Core;
+
+namespace Tgstation.Server.Tests
+{
+ sealed class ConcreteHttpClientFactory : IAbstractHttpClientFactory
+ {
+ public IHttpClient CreateClient() => new HttpClient();
+ }
+}
diff --git a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs
index 8523f37884..1b19569b6f 100644
--- a/tests/Tgstation.Server.Tests/Instance/ByondTest.cs
+++ b/tests/Tgstation.Server.Tests/Instance/ByondTest.cs
@@ -105,12 +105,18 @@ namespace Tgstation.Server.Tests.Instance
var byondInstaller = new PlatformIdentifier().IsWindows
? (IByondInstaller)new WindowsByondInstaller(
Mock.Of(),
- new DefaultIOManager(new AssemblyInformationProvider()),
+ Mock.Of(),
+ new FileDownloader(
+ new ConcreteHttpClientFactory(),
+ Mock.Of>()),
generalConfigOptionsMock.Object,
Mock.Of>())
: new PosixByondInstaller(
Mock.Of(),
- new DefaultIOManager(new AssemblyInformationProvider()),
+ Mock.Of(),
+ new FileDownloader(
+ new ConcreteHttpClientFactory(),
+ Mock.Of>()),
Mock.Of>());
using var windowsByondInstaller = byondInstaller as WindowsByondInstaller;
diff --git a/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs
index f07dd4d8c7..e2bc9c7ebe 100644
--- a/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs
+++ b/tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs
@@ -103,7 +103,7 @@ namespace Tgstation.Server.Tests.Instance
Task SetupDMApiTests(CancellationToken cancellationToken)
{
// just use an I/O manager here
- var ioManager = new DefaultIOManager(new AssemblyInformationProvider());
+ var ioManager = new DefaultIOManager();
return Task.WhenAll(
ioManager.CopyDirectory(
"../../../../DMAPI",
diff --git a/tgstation-server.sln b/tgstation-server.sln
index 063295bfa3..2a7bda3f3d 100644
--- a/tgstation-server.sln
+++ b/tgstation-server.sln
@@ -193,6 +193,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Migrator.C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Common", "src\Tgstation.Server.Host.Common\Tgstation.Server.Host.Common.csproj", "{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tgstation.Server.Common", "src\Tgstation.Server.Common\Tgstation.Server.Common.csproj", "{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -341,6 +343,14 @@ Global
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.Build.0 = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoService|Any CPU.ActiveCfg = Release|Any CPU
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoService|Any CPU.Build.0 = Release|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoService|Any CPU.ActiveCfg = Debug|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoService|Any CPU.Build.0 = Debug|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoService|Any CPU.ActiveCfg = Release|Any CPU
+ {70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoService|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/tools/Tgstation.Server.Migrator/ConcreteHttpClientFactory.cs b/tools/Tgstation.Server.Migrator/ConcreteHttpClientFactory.cs
new file mode 100644
index 0000000000..2a15963fed
--- /dev/null
+++ b/tools/Tgstation.Server.Migrator/ConcreteHttpClientFactory.cs
@@ -0,0 +1,10 @@
+using Tgstation.Server.Common;
+using Tgstation.Server.Host.Core;
+
+namespace Tgstation.Server.Migrator
+{
+ sealed class ConcreteHttpClientFactory : IAbstractHttpClientFactory
+ {
+ public IHttpClient CreateClient() => new HttpClient();
+ }
+}
diff --git a/tools/Tgstation.Server.Migrator/Program.cs b/tools/Tgstation.Server.Migrator/Program.cs
index 0a7cb5654e..298877c75a 100644
--- a/tools/Tgstation.Server.Migrator/Program.cs
+++ b/tools/Tgstation.Server.Migrator/Program.cs
@@ -15,11 +15,15 @@ using System.ServiceProcess;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+
using Octokit;
using Tgstation.Server.Api;
using Tgstation.Server.Client;
+using Tgstation.Server.Host.IO;
using Tgstation.Server.Host.Setup;
+using Tgstation.Server.Migrator;
using FileMode = System.IO.FileMode;
@@ -377,10 +381,14 @@ try
// TGS5 DOWNLOAD AND UNZIP
Console.WriteLine("Downloading TGS5...");
- using (var tgsFiveZipMemoryStream = await SetupApplication.IOManager.DownloadFile(new Uri(serverServiceAsset.BrowserDownloadUrl), default))
+
+ var httpClientFactory = new ConcreteHttpClientFactory();
+ using (var loggerFactory = LoggerFactory.Create(builder => { }))
{
+ var fileDownloader = new FileDownloader(httpClientFactory, loggerFactory.CreateLogger());
+ using var tgsFiveZipMemoryStream = await fileDownloader.DownloadFile(new Uri(serverServiceAsset.BrowserDownloadUrl), default);
Console.WriteLine("Unzipping TGS5...");
- await SetupApplication.IOManager.ZipToDirectory(tgsInstallPath, tgsFiveZipMemoryStream, default);
+ await serverFactory.IOManager.ZipToDirectory(tgsInstallPath, tgsFiveZipMemoryStream, default);
}
// TGS5 CONFIG SETUP