Skip to content

Commit 68611f7

Browse files
authored
Rest di2 (#185)
* another idea * progress
1 parent 499b6ab commit 68611f7

40 files changed

+851
-807
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace OpenLoco.Definitions.Web
2+
{
3+
public static class ApiVersionRoutePrefix
4+
{
5+
public const string V1 = "/v1";
6+
public const string V2 = "/v2";
7+
}
8+
}

Definitions/Web/Client.cs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,42 @@ namespace OpenLoco.Definitions.Web
66
{
77
public static class Client
88
{
9+
public const string ApiVersion = ApiVersionRoutePrefix.V2;
10+
911
public static async Task<IEnumerable<DtoObjectEntry>> GetObjectListAsync(HttpClient client, ILogger? logger = null)
1012
=> await ClientHelpers.GetAsync<IEnumerable<DtoObjectEntry>>(
1113
client,
12-
Routes.Objects,
14+
ApiVersion,
15+
RoutesV2.Objects,
1316
null,
1417
logger) ?? [];
1518

1619
public static async Task<DtoObjectDescriptor?> GetObjectAsync(HttpClient client, int id, ILogger? logger = null)
1720
=> await ClientHelpers.GetAsync<DtoObjectDescriptor>(
1821
client,
19-
Routes.Objects,
22+
ApiVersion,
23+
RoutesV2.Objects,
2024
id,
2125
logger);
2226

2327
public static async Task<byte[]?> GetObjectFileAsync(HttpClient client, int id, ILogger? logger = null)
2428
=> await ClientHelpers.SendRequestAsync(
2529
client,
26-
Routes.Objects + $"/{id}/file",
27-
() => client.GetAsync(Routes.Objects + $"/{id}/file"),
30+
ApiVersion + RoutesV2.Objects + $"/{id}/file",
31+
() => client.GetAsync(RoutesV2.Objects + $"/{id}/file"),
2832
ClientHelpers.ReadBinaryContentAsync,
2933
logger) ?? default;
3034

3135
public static async Task UploadDatFileAsync(HttpClient client, string filename, byte[] datFileBytes, DateTimeOffset creationDate, DateTimeOffset modifiedDate, ILogger logger)
3236
{
3337
var xxHash3 = XxHash3.HashToUInt64(datFileBytes);
34-
logger.Debug($"Posting {filename} to {client.BaseAddress?.OriginalString}{Routes.Objects}");
38+
logger.Debug($"Posting {filename} to {client.BaseAddress?.OriginalString}{RoutesV2.Objects}");
3539
var request = new DtoUploadDat(Convert.ToBase64String(datFileBytes), xxHash3, creationDate, modifiedDate);
36-
_ = await ClientHelpers.PostAsync(client, Routes.Objects, request);
40+
_ = await ClientHelpers.PostAsync(
41+
client,
42+
ApiVersion,
43+
RoutesV2.Objects,
44+
request);
3745
}
3846
}
3947
}

Definitions/Web/ClientHelpers.cs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,42 @@ public static class ClientHelpers
1919
internal static async Task<T?> ReadJsonContentAsync<T>(HttpContent content)
2020
=> await content.ReadFromJsonAsync<T?>();
2121

22-
public static async Task<T?> GetAsync<T>(HttpClient client, string route, int? resourceId = null, ILogger? logger = null)
22+
public static async Task<T?> GetAsync<T>(HttpClient client, string apiRoute, string route, int? resourceId = null, ILogger? logger = null)
2323
=> await SendRequestAsync(
2424
client,
25-
FormRoute(route, resourceId),
26-
() => client.GetAsync(FormRoute(route, resourceId)),
25+
FormRoute(apiRoute, route, resourceId),
26+
() => client.GetAsync(FormRoute(apiRoute, route, resourceId)),
2727
ReadJsonContentAsync<T?>,
2828
logger) ?? default;
2929

30-
public static async Task<bool> DeleteAsync(HttpClient client, string route, int resourceId, ILogger? logger = null)
30+
public static async Task<bool> DeleteAsync(HttpClient client, string apiRoute, string route, int resourceId, ILogger? logger = null)
3131
=> await SendRequestAsync<bool?>(
3232
client,
33-
FormRoute(route, resourceId),
34-
() => client.DeleteAsync(FormRoute(route, resourceId)),
33+
FormRoute(apiRoute, route, resourceId),
34+
() => client.DeleteAsync(FormRoute(apiRoute, route, resourceId)),
3535
null,
3636
logger) != null;
3737

38-
public static async Task<T?> PostAsync<T>(HttpClient client, string route, T request, ILogger? logger = null)
38+
public static async Task<T?> PostAsync<T>(HttpClient client, string apiRoute, string route, T request, ILogger? logger = null)
3939
=> await SendRequestAsync(
4040
client,
41-
FormRoute(route, null),
42-
() => client.PostAsJsonAsync(FormRoute(route, null), request),
41+
FormRoute(apiRoute, route, null),
42+
() => client.PostAsJsonAsync(FormRoute(apiRoute, route, null), request),
4343
ReadJsonContentAsync<T?>,
4444
logger) ?? default;
4545

46-
public static async Task<T?> PutAsync<T>(HttpClient client, string route, int resourceId, T request, ILogger? logger = null)
46+
public static async Task<T?> PutAsync<T>(HttpClient client, string apiRoute, string route, int resourceId, T request, ILogger? logger = null)
4747
=> await SendRequestAsync(
4848
client,
49-
FormRoute(route, resourceId),
50-
() => client.PutAsJsonAsync(FormRoute(route, resourceId), request),
49+
FormRoute(apiRoute, route, resourceId),
50+
() => client.PutAsJsonAsync(FormRoute(apiRoute, route, resourceId), request),
5151
ReadJsonContentAsync<T?>,
5252
logger) ?? default;
5353

54-
static string FormRoute(string baseRoute, int? resourceId)
54+
static string FormRoute(string apiRoute, string baseRoute, int? resourceId)
5555
=> resourceId == null
56-
? baseRoute
57-
: baseRoute + $"/{resourceId}";
56+
? apiRoute + baseRoute
57+
: apiRoute + baseRoute + $"/{resourceId}";
5858

5959
internal static async Task<T?> SendRequestAsync<T>(HttpClient client, string route, Func<Task<HttpResponseMessage>> httpFunc, Func<HttpContent, Task<T?>>? contentReaderFunc = null, ILogger? logger = null)
6060
{
@@ -85,7 +85,7 @@ static string FormRoute(string baseRoute, int? resourceId)
8585
return default;
8686
}
8787

88-
logger?.Debug("Received success response");
88+
logger?.Debug($"Received success response: {response.StatusCode}");
8989

9090
if (contentReaderFunc != null)
9191
{

Definitions/Web/Routes.cs

Lines changed: 0 additions & 55 deletions
This file was deleted.

Definitions/Web/RoutesV1.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace OpenLoco.Definitions.Web
2+
{
3+
public static class RoutesV1
4+
{
5+
// GET
6+
public const string ListObjects = "/objects/list";
7+
8+
public const string GetDat = "/objects/getdat";
9+
public const string GetDatFile = "/objects/getdatfile";
10+
public const string GetObject = "/objects/getobject";
11+
public const string GetObjectFile = "/objects/getobjectfile";
12+
public const string GetObjectImages = "/objects/getobjectimages";
13+
14+
public const string ListObjectPacks = "/objectpacks/list";
15+
public const string GetObjectPack = "/objectpacks/getpack";
16+
17+
public const string ListScenarios = "/scenarios/list";
18+
public const string GetScenario = "/scenarios/getscenario";
19+
20+
public const string ListSC5FilePacks = "/sc5filepacks/list";
21+
public const string GetSC5FilePack = "/sc5filepacks/getpack";
22+
23+
public const string ListAuthors = "/authors/list";
24+
public const string ListLicences = "/licences/list";
25+
public const string ListTags = "/tags/list";
26+
27+
// POST
28+
public const string UploadDat = "/objects/uploaddat";
29+
public const string UploadObject = "/objects/uploadobject";
30+
31+
// PATCH
32+
public const string UpdateDat = "/objects/updatedat";
33+
public const string UpdateObject = "/objects/updateobject";
34+
}
35+
}

Definitions/Web/RoutesV2.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace OpenLoco.Definitions.Web
2+
{
3+
public static class RoutesV2
4+
{
5+
public const string Objects = "/objects";
6+
public const string ObjectPacks = "/objectpacks";
7+
public const string Scenarios = "/scenarios";
8+
public const string SC5FilePacks = "/sc5filepacks";
9+
public const string Authors = "/authors";
10+
public const string Tags = "/tags";
11+
public const string Licences = "/licences";
12+
13+
public const string File = "/file";
14+
public const string Images = "/images";
15+
16+
public const string ResourceRoute = "/{id}";
17+
18+
// Identity
19+
public const string Users = "/users";
20+
public const string Roles = "/roles";
21+
}
22+
}
File renamed without changes.

ObjectService/Program.cs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Microsoft.AspNetCore.HttpLogging;
22
using Microsoft.AspNetCore.RateLimiting;
33
using Microsoft.EntityFrameworkCore;
4+
using ObjectService.RouteHandlers;
5+
using OpenLoco.Dat;
46
using OpenLoco.Definitions.Database;
57
using OpenLoco.ObjectService;
68
using Scalar.AspNetCore;
@@ -25,7 +27,21 @@
2527
});
2628
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
2729
builder.Services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
28-
builder.Services.AddSingleton<Server>();
30+
31+
var objRoot = builder.Configuration["ObjectService:RootFolder"];
32+
var paletteMapFile = builder.Configuration["ObjectService:PaletteMapFile"];
33+
ArgumentNullException.ThrowIfNull(objRoot);
34+
ArgumentNullException.ThrowIfNull(paletteMapFile);
35+
36+
var serverFolderManager = new ServerFolderManager(objRoot);
37+
var paletteMap = new PaletteMap(paletteMapFile);
38+
39+
builder.Services.AddSingleton(serverFolderManager);
40+
builder.Services.AddSingleton(paletteMap);
41+
42+
//var server = new Server(new ServerSettings(objRoot, paletteMapFile));
43+
//builder.Services.AddSingleton(server);
44+
2945
builder.Services.AddHttpLogging(logging =>
3046
{
3147
logging.LoggingFields = HttpLoggingFields.All;
@@ -104,18 +120,20 @@
104120
// defining routes here, after MapLocoIdentityApi, will overwrite them, allowing us to customise them
105121
//app.MapPost("/register", () => Results.Ok());
106122

107-
var objRoot = builder.Configuration["ObjectService:RootFolder"];
108-
var paletteMapFile = builder.Configuration["ObjectService:PaletteMapFile"];
109-
ArgumentNullException.ThrowIfNull(objRoot);
110-
ArgumentNullException.ThrowIfNull(paletteMapFile);
111-
112-
var server = new Server(new ServerSettings(objRoot, paletteMapFile));
113-
114123
_ = app
115-
.MapServerRoutes(server)
116124
.MapHealthChecks("/health")
117125
.RequireRateLimiting(tokenPolicy);
118126

127+
_ = app.MapLegacyRoutes("/v1")
128+
.RequireRateLimiting(tokenPolicy);
129+
130+
_ = app.MapServerRoutes("/v2")
131+
.RequireRateLimiting(tokenPolicy);
132+
133+
_ = app.MapAdminRoutes("/v2")
134+
.RequireAuthorization()
135+
.RequireRateLimiting(tokenPolicy);
136+
119137
var showScalar = builder.Configuration.GetValue<bool?>("ObjectService:ShowScalar");
120138
ArgumentNullException.ThrowIfNull(showScalar);
121139

ObjectService/RouteHandlers/BaseReferenceDataTableRequestHandlerImpl.cs renamed to ObjectService/RouteHandlers/BaseDataTableRouteHandler.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,56 @@
44

55
namespace ObjectService.RouteHandlers
66
{
7-
public static class BaseReferenceDataTableRequestHandlerImpl
7+
public abstract class BaseDataTableRouteHandler<THandler, TDto, TRow> : ITableRouteHandler
8+
where TDto : class, IHasId
9+
where TRow : class, IHasId
10+
where THandler : ITableRouteConfig<TDto, TRow>
11+
{
12+
public static string BaseRoute => THandler.GetBaseRoute();
13+
14+
public static Delegate ListDelegate => ListAsync;
15+
16+
public static Delegate CreateDelegate => CreateAsync;
17+
18+
public static Delegate ReadDelegate => ReadAsync;
19+
20+
public static Delegate UpdateDelegate => UpdateAsync;
21+
22+
public static Delegate DeleteDelegate => DeleteAsync;
23+
24+
public static async Task<IResult> CreateAsync(TDto request, LocoDbContext db)
25+
=> await BaseDataTableRouteHandlerImpl.CreateAsync(
26+
THandler.GetTable(db),
27+
THandler.ToDtoFunc,
28+
THandler.ToRowFunc,
29+
request,
30+
() => (THandler.TryValidateCreate(request, db, out var result), result),
31+
THandler.GetBaseRoute(),
32+
db);
33+
34+
public static async Task<IResult> ReadAsync(DbKey id, LocoDbContext db)
35+
=> await BaseDataTableRouteHandlerImpl.ReadAsync(THandler.GetTable(db), THandler.ToDtoFunc, id, db);
36+
37+
public static async Task<IResult> UpdateAsync(DbKey id, TDto request, LocoDbContext db)
38+
=> await BaseDataTableRouteHandlerImpl.UpdateAsync(
39+
THandler.GetTable(db),
40+
THandler.ToDtoFunc,
41+
THandler.ToRowFunc,
42+
request,
43+
() => (THandler.TryValidateCreate(request, db, out var result), result),
44+
THandler.GetBaseRoute(),
45+
id,
46+
db,
47+
THandler.UpdateFunc);
48+
49+
public static async Task<IResult> DeleteAsync(DbKey id, LocoDbContext db)
50+
=> await BaseDataTableRouteHandlerImpl.DeleteAsync(THandler.GetTable(db), THandler.ToDtoFunc, id, db);
51+
52+
public static async Task<IResult> ListAsync(HttpContext context, LocoDbContext db)
53+
=> await BaseDataTableRouteHandlerImpl.ListAsync(context, THandler.GetTable(db), THandler.ToDtoFunc);
54+
}
55+
56+
public static class BaseDataTableRouteHandlerImpl
857
{
958
public static async Task<IResult> CreateAsync<TDto, TRow>(DbSet<TRow> table, Func<TRow, TDto> dtoConverter, Func<TDto, TRow> rowConverter, TDto request, Func<(bool Success, IResult? ErrorMessage)> tryValidateFunc, string baseRoute, LocoDbContext db)
1059
where TDto : class, IHasId

0 commit comments

Comments
 (0)