remove some old web components, add command line args for no-confirm (skip unreachable server prompt) and kestrel request settings

This commit is contained in:
RaidMax 2023-05-30 14:58:17 -05:00
parent 7d436ac0c5
commit 088f7a51be
8 changed files with 35 additions and 176 deletions

View File

@ -32,11 +32,13 @@
</PackageReference>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="RestEase" Version="1.5.7" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.4.0-alpha.22272.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
</ItemGroup>
<PropertyGroup>
<ServerGarbageCollection>false</ServerGarbageCollection>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<TieredCompilation>true</TieredCompilation>
<LangVersion>Latest</LangVersion>

View File

@ -581,9 +581,9 @@ namespace IW4MAdmin.Application
throw lastException;
}
if (successServers != config.Servers.Length)
if (successServers != config.Servers.Length && !AppContext.TryGetSwitch("NoConfirmPrompt", out _))
{
if (!Utilities.PromptBool(Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"]))
if (!Utilities.CurrentLocalization.LocalizationIndex["MANAGER_START_WITH_ERRORS"].PromptBool())
{
throw lastException;
}

View File

@ -58,7 +58,7 @@ namespace IW4MAdmin.Application
/// entrypoint of the application
/// </summary>
/// <returns></returns>
public static async Task Main(string[] args)
public static async Task Main(bool noConfirm = false, int? maxConcurrentRequests = 25, int? requestQueueLimit = 25)
{
AppDomain.CurrentDomain.SetData("DataDirectory", Utilities.OperatingDirectory);
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
@ -73,7 +73,15 @@ namespace IW4MAdmin.Application
// added to be a bit more permissive with plugin references
return AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(asm => asm.FullName?.StartsWith(libraryName) ?? false);
};
};
if (noConfirm)
{
AppContext.SetSwitch("NoConfirmPrompt", true);
}
Environment.SetEnvironmentVariable("MaxConcurrentRequests", (maxConcurrentRequests * Environment.ProcessorCount).ToString());
Environment.SetEnvironmentVariable("RequestQueueLimit", requestQueueLimit.ToString());
Console.OutputEncoding = Encoding.UTF8;
Console.ForegroundColor = ConsoleColor.Gray;
@ -86,7 +94,7 @@ namespace IW4MAdmin.Application
Console.WriteLine($" Version {Utilities.GetVersionAsString()}");
Console.WriteLine("=====================================================");
await LaunchAsync(args);
await LaunchAsync();
}
/// <summary>
@ -112,13 +120,13 @@ namespace IW4MAdmin.Application
/// task that initializes application and starts the application monitoring and runtime tasks
/// </summary>
/// <returns></returns>
private static async Task LaunchAsync(string[] args)
private static async Task LaunchAsync()
{
restart:
ITranslationLookup translationLookup = null;
var logger = BuildDefaultLogger<Program>(new ApplicationConfiguration());
Utilities.DefaultLogger = logger;
logger.LogInformation("Begin IW4MAdmin startup. Version is {Version} {@Args}", Version, args);
logger.LogInformation("Begin IW4MAdmin startup. Version is {Version}", Version);
try
{
@ -426,9 +434,9 @@ namespace IW4MAdmin.Application
commandConfigHandler.BuildAsync().GetAwaiter().GetResult();
var appConfig = appConfigHandler.Configuration();
var masterUri = /*Utilities.IsDevelopment
var masterUri = Utilities.IsDevelopment
? new Uri("http://127.0.0.1:8080")
: appConfig?.MasterUrl ?? */new ApplicationConfiguration().MasterUrl;
: appConfig?.MasterUrl ?? new ApplicationConfiguration().MasterUrl;
var httpClient = new HttpClient
{
BaseAddress = masterUri,

View File

@ -1,50 +0,0 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace WebfrontCore.Controllers
{
[Route("dynamic")]
public class DynamicFileController : BaseController
{
private static readonly IDictionary<string, string> _fileCache = new Dictionary<string, string>();
public DynamicFileController(IManager manager) : base(manager)
{
}
[Route("css/{fileName}")]
public async Task<IActionResult> Css(string fileName)
{
if (fileName.EndsWith(".css"))
{
if (Utilities.IsDevelopment)
{
var path = Path.Join(Utilities.OperatingDirectory, "..", "..", "..", "..", "WebfrontCore", "wwwroot", "css", fileName);
string cssData = await System.IO.File.ReadAllTextAsync(path);
cssData = await Manager.MiddlewareActionHandler.Execute(cssData, "custom_css_accent");
return Content(cssData, "text/css");
}
if (!_fileCache.ContainsKey(fileName))
{
string path = $"wwwroot{Path.DirectorySeparatorChar}css{Path.DirectorySeparatorChar}{fileName}";
string data = await System.IO.File.ReadAllTextAsync(path);
data = await Manager.MiddlewareActionHandler.Execute(data, "custom_css_accent");
_fileCache.Add(fileName, data);
}
return Content(_fileCache[fileName], "text/css");
}
return StatusCode(400);
}
}
}

View File

@ -1,104 +0,0 @@
using SharedLibraryCore.Interfaces;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
namespace WebfrontCore.Middleware
{
public class CustomCssAccentMiddlewareAction : IMiddlewareAction<string>
{
private readonly List<ColorMap> ColorReplacements = new List<ColorMap>();
private class ColorMap
{
public Color Original { get; set; }
public Color Replacement { get; set; }
}
public CustomCssAccentMiddlewareAction(string originalPrimaryColor, string originalSecondaryColor, string primaryColor, string secondaryColor)
{
primaryColor = string.IsNullOrWhiteSpace(primaryColor) ? originalPrimaryColor : primaryColor;
secondaryColor = string.IsNullOrWhiteSpace(secondaryColor) ? originalSecondaryColor : secondaryColor;
try
{
ColorReplacements.AddRange(new[]
{
new ColorMap()
{
Original = Color.FromArgb(Convert.ToInt32(originalPrimaryColor.Substring(1).ToString(), 16)),
Replacement = Color.FromArgb(Convert.ToInt32(primaryColor.Substring(1).ToString(), 16))
},
new ColorMap()
{
Original = Color.FromArgb(Convert.ToInt32(originalSecondaryColor.Substring(1).ToString(), 16)),
Replacement = Color.FromArgb(Convert.ToInt32(secondaryColor.Substring(1).ToString(), 16))
}
});
}
catch (FormatException)
{
}
}
public Task<string> Invoke(string original)
{
foreach (var color in ColorReplacements)
{
foreach (var shade in new[] { 0, -19, -25 })
{
original = original
.Replace(ColorToHex(LightenDarkenColor(color.Original, shade)), ColorToHex(LightenDarkenColor(color.Replacement, shade)), StringComparison.OrdinalIgnoreCase)
.Replace(ColorToDec(LightenDarkenColor(color.Original, shade)), ColorToDec(LightenDarkenColor(color.Replacement, shade)), StringComparison.OrdinalIgnoreCase);
}
}
return Task.FromResult(original);
}
/// <summary>
/// converts color to the hex string representation
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
private string ColorToHex(Color color) => $"#{color.R.ToString("X2")}{color.G.ToString("X2")}{color.B.ToString("X2")}";
/// <summary>
/// converts color to the rgb tuples representation
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
private string ColorToDec(Color color) => $"{(int)color.R}, {(int)color.G}, {(int)color.B}";
/// <summary>
/// lightens or darkens a color on the given amount
/// Based off SASS darken/lighten function
/// </summary>
/// <param name="color"></param>
/// <param name="amount"></param>
/// <returns></returns>
private Color LightenDarkenColor(Color color, float amount)
{
int r = color.R + (int)((amount / 100.0f) * color.R);
if (r > 255) r = 255;
else if (r < 0) r = 0;
int g = color.G + (int)((amount / 100.0f) * color.G);
if (g > 255) g = 255;
else if (g < 0) g = 0;
int b = color.B + (int)((amount / 100.0f) * color.B);
if (b > 255) b = 255;
else if (b < 0) b = 0;
return Color.FromArgb(r, g, b);
}
}
}

View File

@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using WebfrontCore.Middleware;
namespace WebfrontCore
{
@ -24,11 +23,6 @@ namespace WebfrontCore
public static Task GetWebHostTask(CancellationToken cancellationToken)
{
var config = _webHost.Services.GetRequiredService<ApplicationConfiguration>();
Manager.MiddlewareActionHandler.Register(null,
new CustomCssAccentMiddlewareAction("#007ACC", "#fd7e14", config.WebfrontPrimaryColor,
config.WebfrontSecondaryColor), "custom_css_accent");
return _webHost?.RunAsync(cancellationToken);
}
@ -41,7 +35,12 @@ namespace WebfrontCore
.UseContentRoot(SharedLibraryCore.Utilities.OperatingDirectory)
#endif
.UseUrls(bindUrl)
.UseKestrel()
.UseKestrel(cfg =>
{
cfg.Limits.MaxConcurrentConnections =
int.Parse(Environment.GetEnvironmentVariable("MaxConcurrentRequests") ?? "1");
cfg.Limits.KeepAliveTimeout = TimeSpan.FromSeconds(30);
})
.ConfigureServices(registerDependenciesAction)
.UseStartup<Startup>()
.Build();

View File

@ -4,7 +4,6 @@ using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -24,9 +23,6 @@ using System.Reflection;
using System.Threading.Tasks;
using Data.Abstractions;
using Data.Helpers;
using IW4MAdmin.Plugins.Stats.Helpers;
using Stats.Client.Abstractions;
using Stats.Config;
using WebfrontCore.Controllers.API.Validation;
using WebfrontCore.Middleware;
using WebfrontCore.QueryHelpers;
@ -50,6 +46,12 @@ namespace WebfrontCore
.AllowAnyHeader();
});
});
services.AddStackPolicy(options =>
{
options.MaxConcurrentRequests = int.Parse(Environment.GetEnvironmentVariable("MaxConcurrentRequests") ?? "1");
options.RequestQueueLimit = int.Parse(Environment.GetEnvironmentVariable("RequestQueueLimit") ?? "1");
});
IEnumerable<Assembly> pluginAssemblies()
{
@ -132,6 +134,7 @@ namespace WebfrontCore
app.UseMiddleware<IPWhitelist>(serviceProvider.GetService<ILogger<IPWhitelist>>(), serviceProvider.GetRequiredService<ApplicationConfiguration>().WebfrontConnectionWhitelist);
}
app.UseConcurrencyLimiter();
app.UseStaticFiles();
app.UseAuthentication();
app.UseCors("AllowAll");

View File

@ -25,7 +25,7 @@
</PropertyGroup>
<PropertyGroup>
<ServerGarbageCollection>false</ServerGarbageCollection>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<TieredCompilation>true</TieredCompilation>
<LangVersion>Latest</LangVersion>
@ -47,6 +47,7 @@
<ItemGroup>
<PackageReference Include="BuildWebCompiler2022" Version="1.14.10" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.2.2" />
<PackageReference Include="Microsoft.AspNetCore.ConcurrencyLimiter" Version="6.0.16" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.8" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
</ItemGroup>