using System; using System.Globalization; using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace AMNet.Server; internal static class WebServer { private const int ApiVersion = 1; public static WebApplication BuildServer(params string[] listenAddresses) { var builder = WebApplication.CreateSlimBuilder([]); builder.WebHost.UseUrls(listenAddresses); builder.Logging.ClearProviders(); builder.Logging.AddSimpleConsole(o => { o.SingleLine = true; o.IncludeScopes = false; }); builder.Logging.SetMinimumLevel(LogLevel.Information); builder.Logging.AddFilter("Microsoft.AspNetCore.Http.Result", LogLevel.None); builder.Logging.AddFilter("Microsoft.AspNetCore.Routing.EndpointMiddleware", LogLevel.Error); builder.Services.AddCors(cors => { cors.AddDefaultPolicy(policy => { policy.AllowAnyMethod(); policy.AllowAnyOrigin(); policy.AllowAnyHeader(); policy.SetPreflightMaxAge(TimeSpan.FromHours(6)); }); }); builder.Services.ConfigureHttpJsonOptions(options => { options.SerializerOptions.TypeInfoResolverChain.Insert(0, SerializerContext.Default); }); builder.Services.AddSingleton(); var app = builder.Build(); app.UseCors(); app.MapGet("/amnet/info", () => Results.Ok(new SystemState(ApiVersion, Config.GameId, Config.ServerName))); app.MapPost("/amnet/signin", ProcessCard); return app; } private static async Task ProcessCard(HttpContext ctx) { CardReadRequest request; try { request = await ctx.Request.ReadFromJsonAsync(); } catch (JsonException e) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync(e.Message); return; } if (string.IsNullOrEmpty(request?.MatrixCode)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Card id not provided."); return; } if (request.MatrixCode.Length is 0 or < 20) { ctx.Response.StatusCode = 422; await ctx.Response.WriteAsync("Invalid card id length."); return; } var cardPresenter = ctx.RequestServices.GetRequiredService(); var currentCard = cardPresenter.PeekActiveCard(); if (currentCard?.Expired == false) { var timeLeft = Math.Ceiling(TimeSpan.FromMilliseconds(currentCard.ExpiresAt - Environment.TickCount64).TotalSeconds); ctx.Response.StatusCode = 429; ctx.Response.Headers.RetryAfter = timeLeft.ToString(CultureInfo.InvariantCulture); return; } if (cardPresenter.SetCard(request.MatrixCode) != null) { ctx.Response.StatusCode = 202; } else { ctx.Response.StatusCode = 422; await ctx.Response.WriteAsync("Invalid card id format."); } } }