response handlers fix

This commit is contained in:
Timerix 2025-03-20 19:57:29 +05:00
parent 60f24d6907
commit 0e122adcff
7 changed files with 73 additions and 47 deletions

1
.gitignore vendored
View File

@ -9,6 +9,7 @@
[Ll]og/ [Ll]og/
[Ll]ogs/ [Ll]ogs/
[Pp]ublish/ [Pp]ublish/
data/
# IDE files # IDE files
.vs/ .vs/

View File

@ -6,8 +6,4 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project> </Project>

View File

@ -4,9 +4,9 @@ namespace ParadoxSaveParser.WebAPI;
public static class PathHelper public static class PathHelper
{ {
public const string DATA_DIR = "data"; public const string DATA_DIR = "data";
public static string SAVES_DIR = Path.Join(DATA_DIR, "saves"); public static string SAVES_DIR = Path.Join(DATA_DIR, "saves");
public static string GetMetaFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".meta.json"); public static string GetMetaFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".meta.json");
public static string GetEU4SaveFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".eu4"); public static string GetEU4SaveFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".eu4");
public static string GetParsedSaveFilePath(string save_id) => Path.Join(SAVES_DIR, save_id + ".parsed.json");
} }

View File

@ -1,13 +1,14 @@
global using System; global using System;
global using System.IO;
global using System.Text.Json;
global using System.Threading.Tasks;
global using DTLib.Demystifier;
global using ParadoxSaveParser.Lib;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO;
using System.Linq; using System.Linq;
using System.Text.Json;
using DTLib.Demystifier;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ParadoxSaveParser.Lib;
namespace ParadoxSaveParser.WebAPI; namespace ParadoxSaveParser.WebAPI;
@ -21,6 +22,8 @@ public class Program
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
_app = builder.Build(); _app = builder.Build();
Directory.CreateDirectory(PathHelper.DATA_DIR);
Directory.CreateDirectory(PathHelper.SAVES_DIR);
foreach (var metaFilePath in Directory.GetFiles(PathHelper.SAVES_DIR, "*.meta.json", SearchOption.TopDirectoryOnly)) foreach (var metaFilePath in Directory.GetFiles(PathHelper.SAVES_DIR, "*.meta.json", SearchOption.TopDirectoryOnly))
{ {
using var metaFile = File.Open(metaFilePath, FileMode.Open, FileAccess.Read); using var metaFile = File.Open(metaFilePath, FileMode.Open, FileAccess.Read);
@ -35,40 +38,53 @@ public class Program
} }
_app.UseHttpsRedirection(); _app.UseHttpsRedirection();
_app.MapPost("/parse/eu4", (HttpContext httpContext) => _app.MapGet("/getSaveStatus", GetSaveStatusHandler);
_app.MapPost("/parseSave/eu4", ParseSaveEU4Handler);
_app.Run();
}
private static async Task GetSaveStatusHandler(HttpContext httpContext)
{
httpContext.Request.Query.TryGetValue("id", out var ids);
string? id = ids.FirstOrDefault();
if (string.IsNullOrEmpty(id))
{
throw new BadHttpRequestException("No id provided",
StatusCodes.Status400BadRequest);
}
if (!_saveMetadataStorage.TryGetValue(id, out var meta))
{
throw new BadHttpRequestException($"Save with {id} not found",
StatusCodes.Status400BadRequest);
}
await httpContext.Response.WriteAsJsonAsync(meta);
}
private static async Task ParseSaveEU4Handler(HttpContext httpContext)
{ {
var remoteFile = httpContext.Request.Form.Files.FirstOrDefault(); var remoteFile = httpContext.Request.Form.Files.FirstOrDefault();
if(remoteFile is null || !remoteFile.FileName.EndsWith(".eu4")) if (remoteFile is null || !remoteFile.FileName.EndsWith(".eu4"))
throw new Exception($"Invalid file format: {remoteFile?.FileName}"); {
throw new BadHttpRequestException($"Invalid file format: {remoteFile?.FileName}",
StatusCodes.Status400BadRequest);
}
string saveId = Guid.NewGuid().ToString(); string saveId = Guid.NewGuid().ToString();
string metaFilePath = PathHelper.GetMetaFilePath(saveId); string metaFilePath = PathHelper.GetMetaFilePath(saveId);
if (File.Exists(metaFilePath)) if (File.Exists(metaFilePath))
{ {
httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
throw new Exception($"Guid collision! file {metaFilePath} already exists."); throw new BadHttpRequestException($"Guid collision! file {metaFilePath} already exists.", StatusCodes.Status500InternalServerError);
} }
var meta = new SaveFileMetadata var meta = new SaveFileMetadata { id = saveId, game = Game.EU4, status = SaveFileProcessingStatus.Initialized, };
{
id = saveId,
game = Game.EU4,
status = SaveFileProcessingStatus.Initialized,
};
if (!_saveMetadataStorage.TryAdd(saveId, meta)) if (!_saveMetadataStorage.TryAdd(saveId, meta))
{ {
throw new Exception($"Guid collision! Can't create metadata with id {saveId}"); throw new BadHttpRequestException($"Guid collision! Can't create metadata with id {saveId}", StatusCodes.Status500InternalServerError);
} }
BeginEU4SaveParse(remoteFile, meta);
return meta;
});
_app.Run();
}
private static async void BeginEU4SaveParse(IFormFile remoteFile, SaveFileMetadata meta)
{
try try
{ {
meta.status = SaveFileProcessingStatus.Uploading; meta.status = SaveFileProcessingStatus.Uploading;
@ -76,22 +92,29 @@ public class Program
await using var saveFile = File.Open(saveFilePath, FileMode.CreateNew, FileAccess.ReadWrite); await using var saveFile = File.Open(saveFilePath, FileMode.CreateNew, FileAccess.ReadWrite);
await using (var remoteStream = remoteFile.OpenReadStream()) await using (var remoteStream = remoteFile.OpenReadStream())
{ {
await Task.Delay(50000);
await remoteStream.CopyToAsync(saveFile); await remoteStream.CopyToAsync(saveFile);
} }
meta.status = SaveFileProcessingStatus.Parsing; meta.status = SaveFileProcessingStatus.Parsing;
saveFile.Seek(0, SeekOrigin.Begin); saveFile.Seek(0, SeekOrigin.Begin);
var parser = new ParserEU4(saveFile); var parser = new ParserEU4(saveFile);
//var result = parser.Parse(); var result = parser.Parse();
meta.status = SaveFileProcessingStatus.SavingResults; meta.status = SaveFileProcessingStatus.SavingResults;
// save string resultFilePath = PathHelper.GetParsedSaveFilePath(meta.id);
await using var resultFile = File.Open(resultFilePath, FileMode.CreateNew, FileAccess.Write);
await JsonSerializer.SerializeAsync(resultFile, result);
meta.status = SaveFileProcessingStatus.Done; meta.status = SaveFileProcessingStatus.Done;
meta.SaveToFile();
} }
catch (Exception ex) catch (Exception ex)
{ {
meta.status = SaveFileProcessingStatus.Error; meta.status = SaveFileProcessingStatus.Error;
string errorMesage = ex.ToStringDemystified(); string errorMesage = ex.ToStringDemystified();
meta.errorMesage = errorMesage;
_app.Logger.Log(LogLevel.Error, "EU4SaveParse Error: {errorMesage}", errorMesage); _app.Logger.Log(LogLevel.Error, "EU4SaveParse Error: {errorMesage}", errorMesage);
} }
await httpContext.Response.WriteAsJsonAsync(meta);
} }
} }

View File

@ -12,8 +12,6 @@
"http": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "/",
"applicationUrl": "http://localhost:5226", "applicationUrl": "http://localhost:5226",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
@ -22,8 +20,6 @@
"https": { "https": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "/",
"applicationUrl": "https://localhost:7032;http://localhost:5226", "applicationUrl": "https://localhost:7032;http://localhost:5226",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
@ -31,8 +27,6 @@
}, },
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "/",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

View File

@ -1,5 +1,6 @@
using System.IO; using System.IO;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization;
namespace ParadoxSaveParser.WebAPI; namespace ParadoxSaveParser.WebAPI;
@ -16,9 +17,15 @@ public enum Game
public class SaveFileMetadata public class SaveFileMetadata
{ {
public required string id { get; init; } public required string id { get; init; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public required Game game { get; init; } public required Game game { get; init; }
[JsonConverter(typeof(JsonStringEnumConverter))]
public required SaveFileProcessingStatus status { get; set; } public required SaveFileProcessingStatus status { get; set; }
[JsonIgnore]
public string? errorMesage { get; set; } public string? errorMesage { get; set; }
private static readonly JsonSerializerOptions _jsonOptions = new() { WriteIndented = true }; private static readonly JsonSerializerOptions _jsonOptions = new() { WriteIndented = true };

View File

@ -4,6 +4,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParadoxSaveParser.WebAPI",
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParadoxSaveParser.Lib", "ParadoxSaveParser.Lib\ParadoxSaveParser.Lib.csproj", "{53ED0135-9513-4DE2-9187-CF2899F179B3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParadoxSaveParser.Lib", "ParadoxSaveParser.Lib\ParadoxSaveParser.Lib.csproj", "{53ED0135-9513-4DE2-9187-CF2899F179B3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFolder", "SolutionFolder", "{F1D312F1-0620-4E35-8D78-9A2808CDE12C}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU