diff --git a/LinkRouter/App/Http/Controllers/RedirectController.cs b/LinkRouter/App/Http/Controllers/RedirectController.cs index d4a1750..6a940ad 100644 --- a/LinkRouter/App/Http/Controllers/RedirectController.cs +++ b/LinkRouter/App/Http/Controllers/RedirectController.cs @@ -1,106 +1,30 @@ using LinkRouter.App.Configuration; +using LinkRouter.App.Services; using Microsoft.AspNetCore.Mvc; -using Prometheus; - namespace LinkRouter.App.Http.Controllers; [ApiController] public class RedirectController : Controller { - private readonly Config Config; - - private readonly Counter RouteCounter = Metrics.CreateCounter( - "linkrouter_requests", - "Counts the number of requests to the link router", - new CounterConfiguration - { - LabelNames = new[] { "route" } - } - ); - - - private readonly Counter NotFoundCounter = Metrics.CreateCounter( - "linkrouter_404_requests", - "Counts the number of not found requests to the link router", - new CounterConfiguration - { - LabelNames = new[] { "route" } - } - ); + private readonly RedirectionService RedirectionService; - public RedirectController(Config config) + public RedirectController(Config config, RedirectionService redirectionService) { Config = config; + RedirectionService = redirectionService; } [HttpGet("/{*path}")] public async Task RedirectToExternalUrl(string path) { - if (!path.EndsWith("/")) - path += "/"; - - path = "/" + path; - - Console.WriteLine(path); - - var redirectRoute = Config.CompiledRoutes?.FirstOrDefault(x => x.CompiledPattern.IsMatch(path)); - - if (redirectRoute == null) - { - NotFoundCounter - .WithLabels(path) - .Inc(); - - if (Config.NotFoundBehavior.RedirectOn404) - if (Config.ErrorCodePattern.IsMatch(Config.NotFoundBehavior.RedirectUrl)) - { - var errorCodeMatch = Config.ErrorCodePattern.Match(Config.NotFoundBehavior.RedirectUrl); - var errorCode = int.Parse(errorCodeMatch.Groups[1].Value); - return StatusCode(errorCode); - } else - return Redirect(Config.NotFoundBehavior.RedirectUrl); - - return NotFound(); - } - - var match = redirectRoute.CompiledPattern.Match(path); - - string redirectUrl = redirectRoute.RedirectUrl; - - if (Config.ErrorCodePattern.IsMatch(redirectUrl)) - { - var errorCodeMatch = Config.ErrorCodePattern.Match(redirectUrl); - var errorCode = int.Parse(errorCodeMatch.Groups[1].Value); - return StatusCode(errorCode); - } - - foreach (var placeholder in redirectRoute.Placeholders) - { - var value = match.Groups[placeholder.Value].Value; - redirectUrl = redirectUrl.Replace("{" + placeholder.Key + "}", value); - } - - return Redirect(redirectUrl); + return await RedirectionService.GetRedirect(path); } [HttpGet("/")] - public IActionResult GetRootRoute() + public async Task GetRootRoute() { - RouteCounter - .WithLabels("/") - .Inc(); - - string url = Config.RootRoute; - - if (Config.ErrorCodePattern.IsMatch(url)) - { - var errorCodeMatch = Config.ErrorCodePattern.Match(url); - var errorCode = int.Parse(errorCodeMatch.Groups[1].Value); - return StatusCode(errorCode); - } - - return Redirect(url); + return await RedirectionService.GetRedirect(string.Empty); } } \ No newline at end of file diff --git a/LinkRouter/App/Services/MetricsService.cs b/LinkRouter/App/Services/MetricsService.cs new file mode 100644 index 0000000..56a182a --- /dev/null +++ b/LinkRouter/App/Services/MetricsService.cs @@ -0,0 +1,45 @@ +using MoonCore.Attributes; +using Prometheus; + +namespace LinkRouter.App.Services; + +[Singleton] +public class MetricsService +{ + private readonly Counter RouteCounter = Metrics.CreateCounter( + "linkrouter_requests", + "Counts the number of requests to the link router", + new CounterConfiguration + { + LabelNames = new[] { "route" } + } + ); + + + private readonly Counter NotFoundCounter = Metrics.CreateCounter( + "linkrouter_404_requests", + "Counts the number of not found requests to the link router", + new CounterConfiguration + { + LabelNames = new[] { "route" } + } + ); + + public Task IncrementNotFound(string path) + { + NotFoundCounter + .WithLabels(path) + .Inc(); + + return Task.CompletedTask; + } + + public Task IncrementFound(string path) + { + RouteCounter + .WithLabels(path) + .Inc(); + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/LinkRouter/App/Services/RedirectionService.cs b/LinkRouter/App/Services/RedirectionService.cs new file mode 100644 index 0000000..b6dfefc --- /dev/null +++ b/LinkRouter/App/Services/RedirectionService.cs @@ -0,0 +1,86 @@ +using LinkRouter.App.Configuration; +using Microsoft.AspNetCore.Mvc; +using MoonCore.Attributes; + +namespace LinkRouter.App.Services; + +[Singleton] +public class RedirectionService +{ + private readonly Config Config; + private readonly MetricsService MetricsService; + + public RedirectionService(Config config, MetricsService metricsService) + { + Config = config; + MetricsService = metricsService; + } + + public async Task GetRedirect(string path) + { + if (path == "") + { + var url = Config.RootRoute; + + if (TryGetErrorCode(url, out var notFoundStatusCode)) + return new StatusCodeResult(notFoundStatusCode); + + await MetricsService.IncrementFound("/"); + + return new RedirectResult(url); + } + + if (!path.EndsWith("/")) + path += "/"; + + path = "/" + path; + + + var redirectRoute = Config.CompiledRoutes?.FirstOrDefault(x => x.CompiledPattern.IsMatch(path)); + + + if (redirectRoute == null) + { + await MetricsService.IncrementNotFound(path); + + if (!Config.NotFoundBehavior.RedirectOn404) + return new NotFoundResult(); + + + if (TryGetErrorCode(Config.NotFoundBehavior.RedirectUrl, out var notFoundStatusCode)) + return new StatusCodeResult(notFoundStatusCode); + + return new RedirectResult(Config.NotFoundBehavior.RedirectUrl); + } + + var match = redirectRoute.CompiledPattern.Match(path); + + if (TryGetErrorCode(redirectRoute.RedirectUrl, out var statusCode)) + return new StatusCodeResult(statusCode); + + + foreach (var placeholder in redirectRoute.Placeholders) + { + var value = match.Groups[placeholder.Value].Value; + redirectRoute.RedirectUrl = redirectRoute.RedirectUrl.Replace("{" + placeholder.Key + "}", value); + } + + await MetricsService.IncrementFound(path); + + return new RedirectResult(redirectRoute.RedirectUrl); + } + + private bool TryGetErrorCode(string url, out int code) + { + if (Config.ErrorCodePattern.IsMatch(url)) + { + var errorCodeMatch = Config.ErrorCodePattern.Match(url); + code = int.Parse(errorCodeMatch.Groups[1].Value); + return true; + } + + code = 0; + + return false; + } +} \ No newline at end of file diff --git a/LinkRouter/LinkRouter.csproj b/LinkRouter/LinkRouter.csproj index cf0de1c..07143a2 100644 --- a/LinkRouter/LinkRouter.csproj +++ b/LinkRouter/LinkRouter.csproj @@ -9,10 +9,8 @@ - - + - diff --git a/LinkRouter/Program.cs b/LinkRouter/Program.cs index 4c510be..846359f 100644 --- a/LinkRouter/Program.cs +++ b/LinkRouter/Program.cs @@ -3,6 +3,7 @@ using LinkRouter.App.Services; using MoonCore.Extensions; using MoonCore.Helpers; +using MoonCore.Logging; using Prometheus; namespace LinkRouter; @@ -13,18 +14,13 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - Directory.CreateDirectory(PathBuilder.Dir("data")); + Directory.CreateDirectory(Path.Combine("data")); builder.Services.AddControllers(); - var loggerProviders = LoggerBuildHelper.BuildFromConfiguration(configuration => - { - configuration.Console.Enable = true; - configuration.Console.EnableAnsiMode = true; - }); - builder.Logging.ClearProviders(); - builder.Logging.AddProviders(loggerProviders); + + builder.Logging.AddAnsiConsole(); builder.Services.AddHostedService(); @@ -42,6 +38,8 @@ public static void Main(string[] args) JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true })); builder.Services.AddSingleton(config); + + builder.Services.AutoAddServices(); builder.Services.AddMetricServer(options => { options.Port = 5000; });