From 421b74614dfdbb566165933e980dee0c4dd2d5d8 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 16 Dec 2023 12:25:22 +0000 Subject: [PATCH 1/4] First pass on code cleanup --- checkstyle.xml | 2 +- .../java/net/fabricmc/meta/FabricMeta.java | 2 + .../net/fabricmc/meta/data/DataProvider.java | 21 +++ .../fabricmc/meta/data/VersionDatabase.java | 14 +- .../java/net/fabricmc/meta/web/Endpoint.java | 58 ++++++++ .../net/fabricmc/meta/web/EndpointsV1.java | 112 ---------------- .../net/fabricmc/meta/web/EndpointsV2.java | 2 +- .../java/net/fabricmc/meta/web/JsonModel.java | 21 +++ .../fabricmc/meta/web/ServerBootstrap.java | 2 +- .../java/net/fabricmc/meta/web/WebServer.java | 12 +- .../net/fabricmc/meta/web/v1/EndpointsV1.java | 124 ++++++++++++++++++ .../net/fabricmc/meta/web/v1/ModelsV1.java | 117 +++++++++++++++++ 12 files changed, 359 insertions(+), 128 deletions(-) create mode 100644 src/main/java/net/fabricmc/meta/data/DataProvider.java create mode 100644 src/main/java/net/fabricmc/meta/web/Endpoint.java delete mode 100644 src/main/java/net/fabricmc/meta/web/EndpointsV1.java create mode 100644 src/main/java/net/fabricmc/meta/web/JsonModel.java create mode 100644 src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java create mode 100644 src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java diff --git a/checkstyle.xml b/checkstyle.xml index 2690e6f..015bf1b 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -156,7 +156,7 @@ - + diff --git a/src/main/java/net/fabricmc/meta/FabricMeta.java b/src/main/java/net/fabricmc/meta/FabricMeta.java index e80714f..70f5825 100644 --- a/src/main/java/net/fabricmc/meta/FabricMeta.java +++ b/src/main/java/net/fabricmc/meta/FabricMeta.java @@ -38,6 +38,8 @@ import net.fabricmc.meta.web.WebServer; public class FabricMeta { + // TODO remove all this static access + @Deprecated() public static volatile VersionDatabase database; private static final Logger LOGGER = LoggerFactory.getLogger(VersionDatabase.class); diff --git a/src/main/java/net/fabricmc/meta/data/DataProvider.java b/src/main/java/net/fabricmc/meta/data/DataProvider.java new file mode 100644 index 0000000..a1ad75c --- /dev/null +++ b/src/main/java/net/fabricmc/meta/data/DataProvider.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.data; + +public interface DataProvider { + VersionDatabase getVersionDatabase(); +} diff --git a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java index 8982b3f..3298da0 100644 --- a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java +++ b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java @@ -63,10 +63,8 @@ public static VersionDatabase generate() throws IOException, XMLStreamException database.intermediary = INTERMEDIARY_PARSER.getMeta(MavenVersion::new, "net.fabricmc:intermediary:"); database.loader = LOADER_PARSER.getMeta(MavenBuildVersion::new, "net.fabricmc:fabric-loader:", list -> { for (BaseVersion version : list) { - if (isPublicLoaderVersion(version)) { - version.setStable(true); - break; - } + version.setStable(true); + break; } }); database.installer = INSTALLER_PARSER.getMeta(MavenUrlVersion::new, "net.fabricmc:fabric-installer:"); @@ -114,14 +112,6 @@ private void loadMcData() throws IOException { } public List getLoader() { - return loader.stream().filter(VersionDatabase::isPublicLoaderVersion).collect(Collectors.toList()); - } - - private static boolean isPublicLoaderVersion(BaseVersion version) { - return true; - } - - public List getAllLoader() { return Collections.unmodifiableList(loader); } } diff --git a/src/main/java/net/fabricmc/meta/web/Endpoint.java b/src/main/java/net/fabricmc/meta/web/Endpoint.java new file mode 100644 index 0000000..0416342 --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/Endpoint.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.web; + +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Function; + +import io.javalin.apibuilder.EndpointGroup; +import io.javalin.http.ContentType; +import io.javalin.http.Handler; + +import net.fabricmc.meta.data.DataProvider; + +public abstract class Endpoint { + protected final DataProvider dataProvider; + + protected Endpoint(DataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + public abstract EndpointGroup routes(); + + // Return a json list with no params + protected Handler result(Function> objectSupplier) { + return ctx -> { + List result = objectSupplier.apply(dataProvider); + + ctx.contentType(ContentType.APPLICATION_JSON); + ctx.result(WebServer.GSON.toJson(result)); + }; + } + + // Return a json list with one string param + protected Handler result(String key, BiFunction> objectSupplier) { + return ctx -> { + final String value = ctx.pathParamAsClass(key, String.class).get(); + + List result = objectSupplier.apply(dataProvider, value); + ctx.contentType(ContentType.APPLICATION_JSON); + ctx.result(WebServer.GSON.toJson(result)); + }; + } +} diff --git a/src/main/java/net/fabricmc/meta/web/EndpointsV1.java b/src/main/java/net/fabricmc/meta/web/EndpointsV1.java deleted file mode 100644 index 8bb14e3..0000000 --- a/src/main/java/net/fabricmc/meta/web/EndpointsV1.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2019 FabricMC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package net.fabricmc.meta.web; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import io.javalin.http.Context; - -import net.fabricmc.meta.FabricMeta; -import net.fabricmc.meta.web.models.LoaderInfoV1; -import net.fabricmc.meta.web.models.MavenBuildGameVersion; -import net.fabricmc.meta.web.models.MavenBuildVersion; - -@SuppressWarnings("Duplicates") -public class EndpointsV1 { - public static void setup() { - WebServer.jsonGet("/v1/versions", () -> FabricMeta.database); - - WebServer.jsonGet("/v1/versions/game", () -> FabricMeta.database.game); - WebServer.jsonGet("/v1/versions/game/{game_version}", context -> filter(context, FabricMeta.database.game)); - - WebServer.jsonGet("/v1/versions/mappings", () -> FabricMeta.database.mappings); - WebServer.jsonGet("/v1/versions/mappings/{game_version}", context -> filter(context, FabricMeta.database.mappings)); - - WebServer.jsonGet("/v1/versions/loader", () -> FabricMeta.database.getLoader()); - WebServer.jsonGet("/v1/versions/loader/{game_version}", EndpointsV1::getLoaderInfoAll); - WebServer.jsonGet("/v1/versions/loader/{game_version}/{loader_version}", EndpointsV1::getLoaderInfo); - } - - private static > List filter(Context context, List versionList) { - if (!context.pathParamMap().containsKey("game_version")) { - return Collections.emptyList(); - } - - return versionList.stream().filter(t -> t.test(context.pathParam("game_version"))).collect(Collectors.toList()); - } - - private static Object getLoaderInfo(Context context) { - if (!context.pathParamMap().containsKey("game_version")) { - return null; - } - - if (!context.pathParamMap().containsKey("loader_version")) { - return null; - } - - String gameVersion = context.pathParam("game_version"); - String loaderVersion = context.pathParam("loader_version"); - - MavenBuildVersion loader = FabricMeta.database.getAllLoader().stream() - .filter(mavenBuildVersion -> loaderVersion.equals(mavenBuildVersion.getVersion())) - .findFirst().orElse(null); - - MavenBuildGameVersion mappings = FabricMeta.database.mappings.stream() - .filter(t -> t.test(gameVersion)) - .findFirst().orElse(null); - - if (loader == null) { - context.status(400); - return "no loader version found for " + gameVersion; - } - - if (mappings == null) { - context.status(400); - return "no mappings version found for " + gameVersion; - } - - return new LoaderInfoV1(loader, mappings).populateMeta(); - } - - private static Object getLoaderInfoAll(Context context) { - if (!context.pathParamMap().containsKey("game_version")) { - return null; - } - - String gameVersion = context.pathParam("game_version"); - - MavenBuildGameVersion mappings = FabricMeta.database.mappings.stream() - .filter(t -> t.test(gameVersion)) - .findFirst().orElse(null); - - if (mappings == null) { - return Collections.emptyList(); - } - - List infoList = new ArrayList<>(); - - for (MavenBuildVersion loader : FabricMeta.database.getLoader()) { - infoList.add(new LoaderInfoV1(loader, mappings)); - } - - return infoList; - } -} diff --git a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java b/src/main/java/net/fabricmc/meta/web/EndpointsV2.java index cb488c3..5a99c78 100644 --- a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java +++ b/src/main/java/net/fabricmc/meta/web/EndpointsV2.java @@ -98,7 +98,7 @@ private static Object getLoaderInfo(Context context) { String gameVersion = context.pathParam("game_version"); String loaderVersion = context.pathParam("loader_version"); - MavenBuildVersion loader = FabricMeta.database.getAllLoader().stream() + MavenBuildVersion loader = FabricMeta.database.getLoader().stream() .filter(mavenBuildVersion -> loaderVersion.equals(mavenBuildVersion.getVersion())) .findFirst().orElse(null); diff --git a/src/main/java/net/fabricmc/meta/web/JsonModel.java b/src/main/java/net/fabricmc/meta/web/JsonModel.java new file mode 100644 index 0000000..2bdcf0d --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/JsonModel.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.web; + +// A marker interface for all records that are serialized to JSON as part of the public api. +public interface JsonModel { +} diff --git a/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java b/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java index 2f58149..5d7c2e9 100644 --- a/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java +++ b/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java @@ -62,7 +62,7 @@ private static Handler boostrapHandler() { final String installerVersion = getAndValidateVersion(ctx, FabricMeta.database.installer, "installer_version"); final String gameVersion = getAndValidateVersion(ctx, FabricMeta.database.game, "game_version"); - final String loaderVersion = getAndValidateVersion(ctx, FabricMeta.database.getAllLoader(), "loader_version"); + final String loaderVersion = getAndValidateVersion(ctx, FabricMeta.database.getLoader(), "loader_version"); validateLoaderVersion(loaderVersion); validateInstallerVersion(installerVersion); diff --git a/src/main/java/net/fabricmc/meta/web/WebServer.java b/src/main/java/net/fabricmc/meta/web/WebServer.java index aa514b5..c97c3a5 100644 --- a/src/main/java/net/fabricmc/meta/web/WebServer.java +++ b/src/main/java/net/fabricmc/meta/web/WebServer.java @@ -16,6 +16,8 @@ package net.fabricmc.meta.web; +import static io.javalin.apibuilder.ApiBuilder.path; + import java.util.function.Function; import java.util.function.Supplier; @@ -26,6 +28,9 @@ import io.javalin.http.Header; import io.javalin.plugin.bundled.CorsPluginConfig; +import net.fabricmc.meta.FabricMeta; +import net.fabricmc.meta.web.v1.EndpointsV1; + public class WebServer { public static Javalin javalin; public static Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @@ -41,7 +46,12 @@ public static Javalin create() { config.plugins.enableCors(cors -> cors.add(CorsPluginConfig::anyHost)); }); - EndpointsV1.setup(); + EndpointsV1 endpointsV1 = new EndpointsV1(() -> FabricMeta.database); + + javalin.routes(() -> { + path("v1", endpointsV1.routes()); + }); + EndpointsV2.setup(); return javalin; diff --git a/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java b/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java new file mode 100644 index 0000000..e79e376 --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.web.v1; + +import static io.javalin.apibuilder.ApiBuilder.before; +import static io.javalin.apibuilder.ApiBuilder.get; +import static io.javalin.apibuilder.ApiBuilder.path; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +import io.javalin.apibuilder.EndpointGroup; +import io.javalin.http.BadRequestResponse; +import io.javalin.http.Context; +import io.javalin.http.Handler; +import io.javalin.http.Header; + +import net.fabricmc.meta.data.DataProvider; +import net.fabricmc.meta.web.Endpoint; +import net.fabricmc.meta.web.WebServer; +import net.fabricmc.meta.web.models.LoaderInfoV1; +import net.fabricmc.meta.web.models.MavenBuildGameVersion; +import net.fabricmc.meta.web.models.MavenBuildVersion; + +@SuppressWarnings("Duplicates") +public class EndpointsV1 extends Endpoint { + public EndpointsV1(DataProvider dataProvider) { + super(dataProvider); + } + + @Override + public EndpointGroup routes() { + return () -> { + before(EndpointsV1::beforeHandler); + path("versions", () -> { + get(json(() -> dataProvider.getVersionDatabase())); + get("game", result(ModelsV1::gameVersions)); + get("game/{game_version}", result("game_version", ModelsV1::gameVersions)); + get("mappings", result(ModelsV1::mappingVersions)); + get("mappings/{game_version}", result("game_version", ModelsV1::mappingVersions)); + get("loader", result(ModelsV1::loaderVersions)); + get("loader/{game_version}", json(this::getLoaderInfoAll)); + get("loader/{game_version}/{loader_version}", json(this::getLoaderInfo)); + }); + }; + } + + private static void beforeHandler(Context ctx) { + ctx.header(Header.CACHE_CONTROL, "public, max-age=60"); + } + + @Deprecated + private Handler json(Supplier objectSupplier) { + return ctx -> ctx.result(WebServer.GSON.toJson(objectSupplier.get())); + } + + @Deprecated + private Handler json(Function objectFunction) { + return ctx -> ctx.result(WebServer.GSON.toJson(objectFunction.apply(ctx))); + } + + private LoaderInfoV1 getLoaderInfo(Context context) { + final String gameVersion = context.pathParamAsClass("game_version", String.class).get(); + final String loaderVersion = context.pathParamAsClass("loader_version", String.class).get(); + + MavenBuildVersion loader = dataProvider.getVersionDatabase().getLoader().stream() + .filter(mavenBuildVersion -> loaderVersion.equals(mavenBuildVersion.getVersion())) + .findFirst() + .orElse(null); + + MavenBuildGameVersion mappings = dataProvider.getVersionDatabase().mappings.stream() + .filter(t -> t.test(gameVersion)) + .findFirst() + .orElse(null); + + if (loader == null) { + throw new BadRequestResponse("no loader version found for " + gameVersion); + } + + if (mappings == null) { + throw new BadRequestResponse("no mappings version found for " + gameVersion); + } + + return new LoaderInfoV1(loader, mappings).populateMeta(); + } + + private List getLoaderInfoAll(Context context) { + final String gameVersion = context.pathParamAsClass("game_version", String.class).get(); + + MavenBuildGameVersion mappings = dataProvider.getVersionDatabase().mappings.stream() + .filter(t -> t.test(gameVersion)) + .findFirst() + .orElse(null); + + if (mappings == null) { + return Collections.emptyList(); + } + + List infoList = new LinkedList<>(); + + for (MavenBuildVersion loader : dataProvider.getVersionDatabase().getLoader()) { + infoList.add(new LoaderInfoV1(loader, mappings)); + } + + return infoList; + } +} diff --git a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java new file mode 100644 index 0000000..61e43af --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.web.v1; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import net.fabricmc.meta.data.DataProvider; +import net.fabricmc.meta.web.JsonModel; +import net.fabricmc.meta.web.models.BaseVersion; +import net.fabricmc.meta.web.models.MavenBuildGameVersion; +import net.fabricmc.meta.web.models.MavenBuildVersion; + +/** + * Strongly defined records of the public API. Take extra care to record to method return types here. + */ +public sealed interface ModelsV1 extends JsonModel permits ModelsV1.GameVersion, ModelsV1.MappingVersion, ModelsV1.LoaderVersion { + /** + * /v2/versions/game + */ + static List gameVersions(DataProvider dataProvider) { + LinkedList versions = new LinkedList<>(); + + for (BaseVersion version : dataProvider.getVersionDatabase().game) { + versions.add(GameVersion.from(version)); + } + + return versions; + } + + /** + * /v2/game/{game_version} + */ + static List gameVersions(DataProvider dataProvider, String gameVersion) { + for (BaseVersion version : dataProvider.getVersionDatabase().game) { + if (version.getVersion().equals(gameVersion)) { + return List.of(GameVersion.from(version)); + } + } + + return Collections.emptyList(); + } + + /** + * /v2/versions/mappings + */ + static List mappingVersions(DataProvider dataProvider) { + LinkedList versions = new LinkedList<>(); + + for (MavenBuildGameVersion version : dataProvider.getVersionDatabase().mappings) { + versions.add(MappingVersion.from(version)); + } + + return versions; + } + + /** + * /v2/mappings/{game_version} + */ + static List mappingVersions(DataProvider dataProvider, String gameVersion) { + LinkedList versions = new LinkedList<>(); + + for (MavenBuildGameVersion version : dataProvider.getVersionDatabase().mappings) { + if (version.getGameVersion().equals(gameVersion)) { + versions.add(MappingVersion.from(version)); + } + } + + return versions; + } + + /** + * /v2/versions/loader + */ + static List loaderVersions(DataProvider dataProvider) { + LinkedList versions = new LinkedList<>(); + + for (MavenBuildVersion version : dataProvider.getVersionDatabase().getLoader()) { + versions.add(LoaderVersion.from(version)); + } + + return versions; + } + + record GameVersion(String version, boolean stable) implements ModelsV1 { + private static GameVersion from(BaseVersion version) { + return new GameVersion(version.getVersion(), version.isStable()); + } + } + + record MappingVersion(String gameVersion, String separator, int build, String maven, String version, boolean stable) implements ModelsV1 { + private static MappingVersion from(MavenBuildGameVersion version) { + return new MappingVersion(version.getGameVersion(), version.getSeparator(), version.getBuild(), version.getMaven(), version.getVersion(), version.isStable()); + } + } + + record LoaderVersion(String separator, int build, String maven, String version, boolean stable) implements ModelsV1 { + private static LoaderVersion from(MavenBuildVersion version) { + return new LoaderVersion(version.getSeparator(), version.getBuild(), version.getMaven(), version.getVersion(), version.isStable()); + } + } +} From 551e7ee2e6ed85597c87e4f145596b0dfdad06d6 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sat, 16 Dec 2023 15:20:02 +0000 Subject: [PATCH 2/4] Second pass --- .../java/net/fabricmc/meta/FabricMeta.java | 3 +- .../net/fabricmc/meta/data/DataProvider.java | 31 ++++++ .../fabricmc/meta/data/VersionDatabase.java | 10 +- .../meta/{web => }/models/BaseVersion.java | 2 +- .../meta/{web => }/models/LoaderInfoBase.java | 2 +- .../meta/{web => }/models/LoaderInfoV1.java | 4 +- .../meta/{web => }/models/LoaderInfoV2.java | 4 +- .../models/MavenBuildGameVersion.java | 2 +- .../{web => }/models/MavenBuildVersion.java | 2 +- .../{web => }/models/MavenUrlVersion.java | 2 +- .../meta/{web => }/models/MavenVersion.java | 2 +- .../net/fabricmc/meta/utils/LoaderMeta.java | 15 +-- .../net/fabricmc/meta/utils/PomParser.java | 2 +- .../java/net/fabricmc/meta/web/Endpoint.java | 69 ++++++++++--- .../net/fabricmc/meta/web/ProfileHandler.java | 3 +- .../fabricmc/meta/web/ServerBootstrap.java | 2 +- .../java/net/fabricmc/meta/web/WebServer.java | 34 +++---- .../net/fabricmc/meta/web/v1/EndpointsV1.java | 97 +++---------------- .../net/fabricmc/meta/web/v1/ModelsV1.java | 94 ++++++++++++++++-- .../meta/web/{ => v2}/EndpointsV2.java | 15 +-- .../net/fabricmc/meta/test/TestUtils.java | 28 ++++++ .../test/integration/ComparisonTests.java | 4 +- .../meta/test/unit/EndpointsV2Tests.java | 4 +- .../meta/test/unit/ServerBootstrapTests.java | 4 +- 24 files changed, 274 insertions(+), 161 deletions(-) rename src/main/java/net/fabricmc/meta/{web => }/models/BaseVersion.java (96%) rename src/main/java/net/fabricmc/meta/{web => }/models/LoaderInfoBase.java (94%) rename src/main/java/net/fabricmc/meta/{web => }/models/LoaderInfoV1.java (92%) rename src/main/java/net/fabricmc/meta/{web => }/models/LoaderInfoV2.java (93%) rename src/main/java/net/fabricmc/meta/{web => }/models/MavenBuildGameVersion.java (96%) rename src/main/java/net/fabricmc/meta/{web => }/models/MavenBuildVersion.java (96%) rename src/main/java/net/fabricmc/meta/{web => }/models/MavenUrlVersion.java (96%) rename src/main/java/net/fabricmc/meta/{web => }/models/MavenVersion.java (95%) rename src/main/java/net/fabricmc/meta/web/{ => v2}/EndpointsV2.java (94%) create mode 100644 src/test/java/net/fabricmc/meta/test/TestUtils.java diff --git a/src/main/java/net/fabricmc/meta/FabricMeta.java b/src/main/java/net/fabricmc/meta/FabricMeta.java index 70f5825..68d6771 100644 --- a/src/main/java/net/fabricmc/meta/FabricMeta.java +++ b/src/main/java/net/fabricmc/meta/FabricMeta.java @@ -79,7 +79,8 @@ public static void main(String[] args) { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); executorService.scheduleAtFixedRate(FabricMeta::update, 1, 1, TimeUnit.MINUTES); - WebServer.start(); + WebServer webServer = new WebServer(() -> database); + webServer.createServer().start(5555); } private static void update() { diff --git a/src/main/java/net/fabricmc/meta/data/DataProvider.java b/src/main/java/net/fabricmc/meta/data/DataProvider.java index a1ad75c..ee73424 100644 --- a/src/main/java/net/fabricmc/meta/data/DataProvider.java +++ b/src/main/java/net/fabricmc/meta/data/DataProvider.java @@ -16,6 +16,37 @@ package net.fabricmc.meta.data; +import java.util.List; + +import com.google.gson.JsonObject; + +import net.fabricmc.meta.models.BaseVersion; +import net.fabricmc.meta.models.MavenBuildGameVersion; +import net.fabricmc.meta.models.MavenBuildVersion; +import net.fabricmc.meta.models.MavenVersion; +import net.fabricmc.meta.utils.LoaderMeta; + public interface DataProvider { + @Deprecated // TODO work to remove VersionDatabase getVersionDatabase(); + + default List getGameVersions() { + return getVersionDatabase().game; + } + + default List getMappingVersions() { + return getVersionDatabase().mappings; + } + + default List getIntermediaryVersions() { + return getVersionDatabase().intermediary; + } + + default List getLoaderVersions() { + return getVersionDatabase().getLoader(); + } + + default JsonObject getLoaderInstallerJson(String mavenNotation) { + return LoaderMeta.getMeta(mavenNotation); + } } diff --git a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java index 3298da0..54bd90e 100644 --- a/src/main/java/net/fabricmc/meta/data/VersionDatabase.java +++ b/src/main/java/net/fabricmc/meta/data/VersionDatabase.java @@ -30,13 +30,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.fabricmc.meta.models.BaseVersion; +import net.fabricmc.meta.models.MavenBuildGameVersion; +import net.fabricmc.meta.models.MavenBuildVersion; +import net.fabricmc.meta.models.MavenUrlVersion; +import net.fabricmc.meta.models.MavenVersion; import net.fabricmc.meta.utils.MinecraftLauncherMeta; import net.fabricmc.meta.utils.PomParser; -import net.fabricmc.meta.web.models.BaseVersion; -import net.fabricmc.meta.web.models.MavenBuildGameVersion; -import net.fabricmc.meta.web.models.MavenBuildVersion; -import net.fabricmc.meta.web.models.MavenUrlVersion; -import net.fabricmc.meta.web.models.MavenVersion; public class VersionDatabase { public static final PomParser MAPPINGS_PARSER = new PomParser(LOCAL_FABRIC_MAVEN_URL + "net/fabricmc/yarn/maven-metadata.xml"); diff --git a/src/main/java/net/fabricmc/meta/web/models/BaseVersion.java b/src/main/java/net/fabricmc/meta/models/BaseVersion.java similarity index 96% rename from src/main/java/net/fabricmc/meta/web/models/BaseVersion.java rename to src/main/java/net/fabricmc/meta/models/BaseVersion.java index fd2dd39..e6f7a6b 100644 --- a/src/main/java/net/fabricmc/meta/web/models/BaseVersion.java +++ b/src/main/java/net/fabricmc/meta/models/BaseVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; import java.util.function.Predicate; diff --git a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoBase.java b/src/main/java/net/fabricmc/meta/models/LoaderInfoBase.java similarity index 94% rename from src/main/java/net/fabricmc/meta/web/models/LoaderInfoBase.java rename to src/main/java/net/fabricmc/meta/models/LoaderInfoBase.java index 41f6a23..6323028 100644 --- a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoBase.java +++ b/src/main/java/net/fabricmc/meta/models/LoaderInfoBase.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; public interface LoaderInfoBase { MavenBuildVersion getLoader(); diff --git a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoV1.java b/src/main/java/net/fabricmc/meta/models/LoaderInfoV1.java similarity index 92% rename from src/main/java/net/fabricmc/meta/web/models/LoaderInfoV1.java rename to src/main/java/net/fabricmc/meta/models/LoaderInfoV1.java index 5523c7a..90a077e 100644 --- a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoV1.java +++ b/src/main/java/net/fabricmc/meta/models/LoaderInfoV1.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; import com.google.gson.JsonObject; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ public LoaderInfoV1(MavenBuildVersion loader, MavenBuildGameVersion mappings) { } public LoaderInfoV1 populateMeta() { - launcherMeta = LoaderMeta.getMeta(this); + launcherMeta = LoaderMeta.getMeta(getLoader().getMaven()); return this; } diff --git a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoV2.java b/src/main/java/net/fabricmc/meta/models/LoaderInfoV2.java similarity index 93% rename from src/main/java/net/fabricmc/meta/web/models/LoaderInfoV2.java rename to src/main/java/net/fabricmc/meta/models/LoaderInfoV2.java index 0547f43..d8d569a 100644 --- a/src/main/java/net/fabricmc/meta/web/models/LoaderInfoV2.java +++ b/src/main/java/net/fabricmc/meta/models/LoaderInfoV2.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; import com.google.gson.JsonObject; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ public LoaderInfoV2(MavenBuildVersion loader, MavenVersion intermediary) { } public LoaderInfoV2 populateMeta() { - launcherMeta = LoaderMeta.getMeta(this); + launcherMeta = LoaderMeta.getMeta(getLoader().getMaven()); return this; } diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenBuildGameVersion.java b/src/main/java/net/fabricmc/meta/models/MavenBuildGameVersion.java similarity index 96% rename from src/main/java/net/fabricmc/meta/web/models/MavenBuildGameVersion.java rename to src/main/java/net/fabricmc/meta/models/MavenBuildGameVersion.java index dd13358..14d8f0d 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenBuildGameVersion.java +++ b/src/main/java/net/fabricmc/meta/models/MavenBuildGameVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; import net.fabricmc.meta.utils.YarnVersionParser; diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java b/src/main/java/net/fabricmc/meta/models/MavenBuildVersion.java similarity index 96% rename from src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java rename to src/main/java/net/fabricmc/meta/models/MavenBuildVersion.java index 104a299..bc282b8 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenBuildVersion.java +++ b/src/main/java/net/fabricmc/meta/models/MavenBuildVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; public class MavenBuildVersion extends MavenVersion { String separator; diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenUrlVersion.java b/src/main/java/net/fabricmc/meta/models/MavenUrlVersion.java similarity index 96% rename from src/main/java/net/fabricmc/meta/web/models/MavenUrlVersion.java rename to src/main/java/net/fabricmc/meta/models/MavenUrlVersion.java index 010f322..69b0654 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenUrlVersion.java +++ b/src/main/java/net/fabricmc/meta/models/MavenUrlVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; import net.fabricmc.meta.utils.Reference; diff --git a/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java b/src/main/java/net/fabricmc/meta/models/MavenVersion.java similarity index 95% rename from src/main/java/net/fabricmc/meta/web/models/MavenVersion.java rename to src/main/java/net/fabricmc/meta/models/MavenVersion.java index 162ea30..4cb099e 100644 --- a/src/main/java/net/fabricmc/meta/web/models/MavenVersion.java +++ b/src/main/java/net/fabricmc/meta/models/MavenVersion.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web.models; +package net.fabricmc.meta.models; public class MavenVersion extends BaseVersion { String maven; diff --git a/src/main/java/net/fabricmc/meta/utils/LoaderMeta.java b/src/main/java/net/fabricmc/meta/utils/LoaderMeta.java index 2bb910d..e62a943 100644 --- a/src/main/java/net/fabricmc/meta/utils/LoaderMeta.java +++ b/src/main/java/net/fabricmc/meta/utils/LoaderMeta.java @@ -22,17 +22,18 @@ import java.io.IOException; import java.net.URL; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; import org.apache.commons.io.FileUtils; - -import net.fabricmc.meta.web.WebServer; -import net.fabricmc.meta.web.models.LoaderInfoBase; +import org.jetbrains.annotations.Nullable; public class LoaderMeta { - public static final File BASE_DIR = new File("metadata"); + private static final File BASE_DIR = new File("metadata"); + private static final Gson GSON = new GsonBuilder().create(); - public static JsonObject getMeta(LoaderInfoBase loaderInfo) { - String loaderMaven = loaderInfo.getLoader().getMaven(); + @Nullable + public static JsonObject getMeta(String loaderMaven) { String[] split = loaderMaven.split(":"); String path = String.format("%s/%s/%s", split[0].replaceAll("\\.", "/"), split[1], split[2]); String filename = String.format("%s-%s.json", split[1], split[2]); @@ -51,7 +52,7 @@ public static JsonObject getMeta(LoaderInfoBase loaderInfo) { } try { - JsonObject jsonObject = WebServer.GSON.fromJson(new FileReader(launcherMetaFile), JsonObject.class); + JsonObject jsonObject = GSON.fromJson(new FileReader(launcherMetaFile), JsonObject.class); return jsonObject; } catch (FileNotFoundException e) { e.printStackTrace(); diff --git a/src/main/java/net/fabricmc/meta/utils/PomParser.java b/src/main/java/net/fabricmc/meta/utils/PomParser.java index 862ff27..ae7dc59 100644 --- a/src/main/java/net/fabricmc/meta/utils/PomParser.java +++ b/src/main/java/net/fabricmc/meta/utils/PomParser.java @@ -33,7 +33,7 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import net.fabricmc.meta.web.models.BaseVersion; +import net.fabricmc.meta.models.BaseVersion; public class PomParser { public String path; diff --git a/src/main/java/net/fabricmc/meta/web/Endpoint.java b/src/main/java/net/fabricmc/meta/web/Endpoint.java index 0416342..5f7951b 100644 --- a/src/main/java/net/fabricmc/meta/web/Endpoint.java +++ b/src/main/java/net/fabricmc/meta/web/Endpoint.java @@ -16,17 +16,21 @@ package net.fabricmc.meta.web; +import java.time.Duration; import java.util.List; -import java.util.function.BiFunction; -import java.util.function.Function; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import io.javalin.apibuilder.EndpointGroup; import io.javalin.http.ContentType; +import io.javalin.http.Context; import io.javalin.http.Handler; import net.fabricmc.meta.data.DataProvider; public abstract class Endpoint { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + protected final DataProvider dataProvider; protected Endpoint(DataProvider dataProvider) { @@ -35,24 +39,67 @@ protected Endpoint(DataProvider dataProvider) { public abstract EndpointGroup routes(); - // Return a json list with no params - protected Handler result(Function> objectSupplier) { + protected Handler cache(Duration duration) { return ctx -> { - List result = objectSupplier.apply(dataProvider); + ctx.header("Cache-Control", "public, max-age=" + duration.getSeconds()); + }; + } - ctx.contentType(ContentType.APPLICATION_JSON); - ctx.result(WebServer.GSON.toJson(result)); + // Return a json list with no params + protected Handler result(JsonListHandler handler) { + return ctx -> { + List result = handler.apply(dataProvider); + jsonResult(ctx, result); }; } // Return a json list with one string param - protected Handler result(String key, BiFunction> objectSupplier) { + protected Handler result(String key, JsonListHandler1 handler) { return ctx -> { final String value = ctx.pathParamAsClass(key, String.class).get(); + List result = handler.apply(dataProvider, value); + jsonResult(ctx, result); + }; + } - List result = objectSupplier.apply(dataProvider, value); - ctx.contentType(ContentType.APPLICATION_JSON); - ctx.result(WebServer.GSON.toJson(result)); + // Return a json list with two string params + protected Handler result(String key1, String key2, JsonListHandler2 handler) { + return ctx -> { + final String value1 = ctx.pathParamAsClass(key1, String.class).get(); + final String value2 = ctx.pathParamAsClass(key2, String.class).get(); + List result = handler.apply(dataProvider, value1, value2); + jsonResult(ctx, result); }; } + + // Return a json list with two string params + protected Handler result(String key1, String key2, JsonHandler2 handler) { + return ctx -> { + final String value1 = ctx.pathParamAsClass(key1, String.class).get(); + final String value2 = ctx.pathParamAsClass(key2, String.class).get(); + JsonModel result = handler.apply(dataProvider, value1, value2); + jsonResult(ctx, result); + }; + } + + protected void jsonResult(Context ctx, Object result) { + ctx.contentType(ContentType.APPLICATION_JSON); + ctx.result(GSON.toJson(result)); + } + + protected interface JsonListHandler { + List apply(DataProvider dataProvider); + } + + protected interface JsonListHandler1 { + List apply(DataProvider dataProvider, String key1); + } + + protected interface JsonListHandler2 { + List apply(DataProvider dataProvider, String key1, String key2); + } + + protected interface JsonHandler2 { + JsonModel apply(DataProvider dataProvider, String key1, String key2); + } } diff --git a/src/main/java/net/fabricmc/meta/web/ProfileHandler.java b/src/main/java/net/fabricmc/meta/web/ProfileHandler.java index 8cc3ced..0935fec 100644 --- a/src/main/java/net/fabricmc/meta/web/ProfileHandler.java +++ b/src/main/java/net/fabricmc/meta/web/ProfileHandler.java @@ -35,8 +35,9 @@ import com.google.gson.JsonObject; import org.apache.commons.io.IOUtils; +import net.fabricmc.meta.models.LoaderInfoV2; import net.fabricmc.meta.utils.Reference; -import net.fabricmc.meta.web.models.LoaderInfoV2; +import net.fabricmc.meta.web.v2.EndpointsV2; public class ProfileHandler { private static final Executor EXECUTOR = Executors.newFixedThreadPool(2); diff --git a/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java b/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java index 5d7c2e9..1292095 100644 --- a/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java +++ b/src/main/java/net/fabricmc/meta/web/ServerBootstrap.java @@ -41,8 +41,8 @@ import org.apache.commons.io.FileUtils; import net.fabricmc.meta.FabricMeta; +import net.fabricmc.meta.models.BaseVersion; import net.fabricmc.meta.utils.Reference; -import net.fabricmc.meta.web.models.BaseVersion; public class ServerBootstrap { private static final Path CACHE_DIR = Paths.get("metadata", "installer"); diff --git a/src/main/java/net/fabricmc/meta/web/WebServer.java b/src/main/java/net/fabricmc/meta/web/WebServer.java index c97c3a5..03fd248 100644 --- a/src/main/java/net/fabricmc/meta/web/WebServer.java +++ b/src/main/java/net/fabricmc/meta/web/WebServer.java @@ -28,40 +28,40 @@ import io.javalin.http.Header; import io.javalin.plugin.bundled.CorsPluginConfig; -import net.fabricmc.meta.FabricMeta; +import net.fabricmc.meta.data.DataProvider; import net.fabricmc.meta.web.v1.EndpointsV1; +import net.fabricmc.meta.web.v2.EndpointsV2; public class WebServer { + @Deprecated(forRemoval = true) public static Javalin javalin; - public static Gson GSON = new GsonBuilder().setPrettyPrinting().create(); - public static Javalin create() { - if (javalin != null) { - javalin.stop(); - } + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + + private final DataProvider dataProvider; + private final EndpointsV1 endpointsV1; - javalin = Javalin.create(config -> { + public WebServer(DataProvider dataProvider) { + this.dataProvider = dataProvider; + endpointsV1 = new EndpointsV1(dataProvider); + } + + public Javalin createServer() { + Javalin javalin = Javalin.create(config -> { config.plugins.enableRouteOverview("/"); config.showJavalinBanner = false; config.plugins.enableCors(cors -> cors.add(CorsPluginConfig::anyHost)); - }); - - EndpointsV1 endpointsV1 = new EndpointsV1(() -> FabricMeta.database); - - javalin.routes(() -> { + }).routes(() -> { path("v1", endpointsV1.routes()); }); + // TODO remove this + WebServer.javalin = javalin; EndpointsV2.setup(); return javalin; } - public static void start() { - assert javalin == null; - create().start(5555); - } - public static void jsonGet(String route, Supplier supplier) { javalin.get(route, ctx -> { T object = supplier.get(); diff --git a/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java b/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java index e79e376..83bbe45 100644 --- a/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java +++ b/src/main/java/net/fabricmc/meta/web/v1/EndpointsV1.java @@ -18,28 +18,14 @@ import static io.javalin.apibuilder.ApiBuilder.before; import static io.javalin.apibuilder.ApiBuilder.get; -import static io.javalin.apibuilder.ApiBuilder.path; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Function; -import java.util.function.Supplier; +import java.time.Duration; import io.javalin.apibuilder.EndpointGroup; -import io.javalin.http.BadRequestResponse; -import io.javalin.http.Context; -import io.javalin.http.Handler; -import io.javalin.http.Header; import net.fabricmc.meta.data.DataProvider; import net.fabricmc.meta.web.Endpoint; -import net.fabricmc.meta.web.WebServer; -import net.fabricmc.meta.web.models.LoaderInfoV1; -import net.fabricmc.meta.web.models.MavenBuildGameVersion; -import net.fabricmc.meta.web.models.MavenBuildVersion; -@SuppressWarnings("Duplicates") public class EndpointsV1 extends Endpoint { public EndpointsV1(DataProvider dataProvider) { super(dataProvider); @@ -48,77 +34,16 @@ public EndpointsV1(DataProvider dataProvider) { @Override public EndpointGroup routes() { return () -> { - before(EndpointsV1::beforeHandler); - path("versions", () -> { - get(json(() -> dataProvider.getVersionDatabase())); - get("game", result(ModelsV1::gameVersions)); - get("game/{game_version}", result("game_version", ModelsV1::gameVersions)); - get("mappings", result(ModelsV1::mappingVersions)); - get("mappings/{game_version}", result("game_version", ModelsV1::mappingVersions)); - get("loader", result(ModelsV1::loaderVersions)); - get("loader/{game_version}", json(this::getLoaderInfoAll)); - get("loader/{game_version}/{loader_version}", json(this::getLoaderInfo)); - }); + before(cache(Duration.ofMinutes(1))); + + get("versions", ctx -> jsonResult(ctx, dataProvider.getVersionDatabase())); + get("versions/game", result(ModelsV1::gameVersions)); + get("versions/game/{game_version}", result("game_version", ModelsV1::gameVersions)); + get("versions/mappings", result(ModelsV1::mappingVersions)); + get("versions/mappings/{game_version}", result("game_version", ModelsV1::mappingVersions)); + get("versions/loader", result(ModelsV1::loaderVersions)); + get("versions/loader/{game_version}", result("game_version", ModelsV1::loaderInfo)); + get("versions/loader/{game_version}/{loader_version}", result("game_version", "loader_version", ModelsV1::loaderLauncherInfo)); }; } - - private static void beforeHandler(Context ctx) { - ctx.header(Header.CACHE_CONTROL, "public, max-age=60"); - } - - @Deprecated - private Handler json(Supplier objectSupplier) { - return ctx -> ctx.result(WebServer.GSON.toJson(objectSupplier.get())); - } - - @Deprecated - private Handler json(Function objectFunction) { - return ctx -> ctx.result(WebServer.GSON.toJson(objectFunction.apply(ctx))); - } - - private LoaderInfoV1 getLoaderInfo(Context context) { - final String gameVersion = context.pathParamAsClass("game_version", String.class).get(); - final String loaderVersion = context.pathParamAsClass("loader_version", String.class).get(); - - MavenBuildVersion loader = dataProvider.getVersionDatabase().getLoader().stream() - .filter(mavenBuildVersion -> loaderVersion.equals(mavenBuildVersion.getVersion())) - .findFirst() - .orElse(null); - - MavenBuildGameVersion mappings = dataProvider.getVersionDatabase().mappings.stream() - .filter(t -> t.test(gameVersion)) - .findFirst() - .orElse(null); - - if (loader == null) { - throw new BadRequestResponse("no loader version found for " + gameVersion); - } - - if (mappings == null) { - throw new BadRequestResponse("no mappings version found for " + gameVersion); - } - - return new LoaderInfoV1(loader, mappings).populateMeta(); - } - - private List getLoaderInfoAll(Context context) { - final String gameVersion = context.pathParamAsClass("game_version", String.class).get(); - - MavenBuildGameVersion mappings = dataProvider.getVersionDatabase().mappings.stream() - .filter(t -> t.test(gameVersion)) - .findFirst() - .orElse(null); - - if (mappings == null) { - return Collections.emptyList(); - } - - List infoList = new LinkedList<>(); - - for (MavenBuildVersion loader : dataProvider.getVersionDatabase().getLoader()) { - infoList.add(new LoaderInfoV1(loader, mappings)); - } - - return infoList; - } } diff --git a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java index 61e43af..c6d7975 100644 --- a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java +++ b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java @@ -20,23 +20,27 @@ import java.util.LinkedList; import java.util.List; +import com.google.gson.JsonObject; +import io.javalin.http.BadRequestResponse; +import io.javalin.http.InternalServerErrorResponse; + import net.fabricmc.meta.data.DataProvider; +import net.fabricmc.meta.models.BaseVersion; +import net.fabricmc.meta.models.MavenBuildGameVersion; +import net.fabricmc.meta.models.MavenBuildVersion; import net.fabricmc.meta.web.JsonModel; -import net.fabricmc.meta.web.models.BaseVersion; -import net.fabricmc.meta.web.models.MavenBuildGameVersion; -import net.fabricmc.meta.web.models.MavenBuildVersion; /** * Strongly defined records of the public API. Take extra care to record to method return types here. */ -public sealed interface ModelsV1 extends JsonModel permits ModelsV1.GameVersion, ModelsV1.MappingVersion, ModelsV1.LoaderVersion { +public sealed interface ModelsV1 extends JsonModel permits ModelsV1.GameVersion, ModelsV1.MappingVersion, ModelsV1.LoaderVersion, ModelsV1.LoaderInfo, ModelsV1.LoaderLauncherInfo { /** * /v2/versions/game */ static List gameVersions(DataProvider dataProvider) { LinkedList versions = new LinkedList<>(); - for (BaseVersion version : dataProvider.getVersionDatabase().game) { + for (BaseVersion version : dataProvider.getGameVersions()) { versions.add(GameVersion.from(version)); } @@ -47,7 +51,7 @@ static List gameVersions(DataProvider dataProvider) { * /v2/game/{game_version} */ static List gameVersions(DataProvider dataProvider, String gameVersion) { - for (BaseVersion version : dataProvider.getVersionDatabase().game) { + for (BaseVersion version : dataProvider.getGameVersions()) { if (version.getVersion().equals(gameVersion)) { return List.of(GameVersion.from(version)); } @@ -62,7 +66,7 @@ static List gameVersions(DataProvider dataProvider, String gameVers static List mappingVersions(DataProvider dataProvider) { LinkedList versions = new LinkedList<>(); - for (MavenBuildGameVersion version : dataProvider.getVersionDatabase().mappings) { + for (MavenBuildGameVersion version : dataProvider.getMappingVersions()) { versions.add(MappingVersion.from(version)); } @@ -75,7 +79,7 @@ static List mappingVersions(DataProvider dataProvider) { static List mappingVersions(DataProvider dataProvider, String gameVersion) { LinkedList versions = new LinkedList<>(); - for (MavenBuildGameVersion version : dataProvider.getVersionDatabase().mappings) { + for (MavenBuildGameVersion version : dataProvider.getMappingVersions()) { if (version.getGameVersion().equals(gameVersion)) { versions.add(MappingVersion.from(version)); } @@ -90,13 +94,81 @@ static List mappingVersions(DataProvider dataProvider, String ga static List loaderVersions(DataProvider dataProvider) { LinkedList versions = new LinkedList<>(); - for (MavenBuildVersion version : dataProvider.getVersionDatabase().getLoader()) { + for (MavenBuildVersion version : dataProvider.getLoaderVersions()) { versions.add(LoaderVersion.from(version)); } return versions; } + /** + * /v2/versions/loader/{game_version}/{loader_version} + */ + static List loaderInfo(DataProvider dataProvider, String gameVersion) { + MavenBuildGameVersion mappings = null; + + for (MavenBuildGameVersion version : dataProvider.getMappingVersions()) { + if (version.test(gameVersion)) { + mappings = version; + break; + } + } + + if (mappings == null) { + return Collections.emptyList(); + } + + List infoList = new LinkedList<>(); + + for (MavenBuildVersion loader : dataProvider.getLoaderVersions()) { + infoList.add(new LoaderInfo(LoaderVersion.from(loader), MappingVersion.from(mappings))); + } + + return infoList; + } + + /** + * /v2/versions/loader/{game_version}/{loader_version} + */ + static LoaderLauncherInfo loaderLauncherInfo(DataProvider dataProvider, String gameVersion, String loaderVersion) { + MavenBuildVersion loader = null; + MavenBuildGameVersion mappings = null; + + for (MavenBuildVersion version : dataProvider.getLoaderVersions()) { + if (loaderVersion.equals(version.getVersion())) { + loader = version; + break; + } + } + + for (MavenBuildGameVersion version : dataProvider.getMappingVersions()) { + if (version.test(gameVersion)) { + mappings = version; + break; + } + } + + if (loader == null) { + throw new BadRequestResponse("no loader version found for " + gameVersion); + } + + if (mappings == null) { + throw new BadRequestResponse("no mappings version found for " + gameVersion); + } + + final JsonObject installerJson = dataProvider.getLoaderInstallerJson(loader.getMaven()); + + if (installerJson == null) { + throw new InternalServerErrorResponse("Failed to load installer json, report to Fabric"); + } + + return new LoaderLauncherInfo( + LoaderVersion.from(loader), + MappingVersion.from(mappings), + installerJson + ); + } + record GameVersion(String version, boolean stable) implements ModelsV1 { private static GameVersion from(BaseVersion version) { return new GameVersion(version.getVersion(), version.isStable()); @@ -114,4 +186,8 @@ private static LoaderVersion from(MavenBuildVersion version) { return new LoaderVersion(version.getSeparator(), version.getBuild(), version.getMaven(), version.getVersion(), version.isStable()); } } + + record LoaderInfo(LoaderVersion loader, MappingVersion mappings) implements ModelsV1 { } + + record LoaderLauncherInfo(LoaderVersion loader, MappingVersion mappings, Object launcherMeta) implements ModelsV1 { } } diff --git a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java b/src/main/java/net/fabricmc/meta/web/v2/EndpointsV2.java similarity index 94% rename from src/main/java/net/fabricmc/meta/web/EndpointsV2.java rename to src/main/java/net/fabricmc/meta/web/v2/EndpointsV2.java index 5a99c78..5a55311 100644 --- a/src/main/java/net/fabricmc/meta/web/EndpointsV2.java +++ b/src/main/java/net/fabricmc/meta/web/v2/EndpointsV2.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.meta.web; +package net.fabricmc.meta.web.v2; import java.io.InputStream; import java.util.ArrayList; @@ -30,11 +30,14 @@ import io.javalin.http.Header; import net.fabricmc.meta.FabricMeta; -import net.fabricmc.meta.web.models.BaseVersion; -import net.fabricmc.meta.web.models.LoaderInfoV2; -import net.fabricmc.meta.web.models.MavenBuildGameVersion; -import net.fabricmc.meta.web.models.MavenBuildVersion; -import net.fabricmc.meta.web.models.MavenVersion; +import net.fabricmc.meta.models.BaseVersion; +import net.fabricmc.meta.models.LoaderInfoV2; +import net.fabricmc.meta.models.MavenBuildGameVersion; +import net.fabricmc.meta.models.MavenBuildVersion; +import net.fabricmc.meta.models.MavenVersion; +import net.fabricmc.meta.web.ProfileHandler; +import net.fabricmc.meta.web.ServerBootstrap; +import net.fabricmc.meta.web.WebServer; @SuppressWarnings("Duplicates") public class EndpointsV2 { diff --git a/src/test/java/net/fabricmc/meta/test/TestUtils.java b/src/test/java/net/fabricmc/meta/test/TestUtils.java new file mode 100644 index 0000000..ee97998 --- /dev/null +++ b/src/test/java/net/fabricmc/meta/test/TestUtils.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.test; + +import io.javalin.Javalin; + +import net.fabricmc.meta.FabricMeta; +import net.fabricmc.meta.web.WebServer; + +public class TestUtils { + public static Javalin createServer() { + return new WebServer(() -> FabricMeta.database).createServer(); + } +} diff --git a/src/test/java/net/fabricmc/meta/test/integration/ComparisonTests.java b/src/test/java/net/fabricmc/meta/test/integration/ComparisonTests.java index f8b21d3..a35986f 100644 --- a/src/test/java/net/fabricmc/meta/test/integration/ComparisonTests.java +++ b/src/test/java/net/fabricmc/meta/test/integration/ComparisonTests.java @@ -32,7 +32,7 @@ import org.junit.jupiter.params.provider.MethodSource; import net.fabricmc.meta.FabricMeta; -import net.fabricmc.meta.web.WebServer; +import net.fabricmc.meta.test.TestUtils; // Tests that the local response matches the remote response of the version in prod public class ComparisonTests { @@ -79,7 +79,7 @@ public static Stream provideEndpoints() { @ParameterizedTest @MethodSource("provideEndpoints") void compareEndpoint(String endpoint) { - JavalinTest.test(WebServer.create(), (server, client) -> { + JavalinTest.test(TestUtils.createServer(), (server, client) -> { compareEndpoint(endpoint, client); }); } diff --git a/src/test/java/net/fabricmc/meta/test/unit/EndpointsV2Tests.java b/src/test/java/net/fabricmc/meta/test/unit/EndpointsV2Tests.java index 915000d..d3d3a78 100644 --- a/src/test/java/net/fabricmc/meta/test/unit/EndpointsV2Tests.java +++ b/src/test/java/net/fabricmc/meta/test/unit/EndpointsV2Tests.java @@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test; import net.fabricmc.meta.FabricMeta; -import net.fabricmc.meta.web.WebServer; +import net.fabricmc.meta.test.TestUtils; public class EndpointsV2Tests { @BeforeAll @@ -35,7 +35,7 @@ static void beforeAll() { @Test void versions() { - JavalinTest.test(WebServer.create(), (server, client) -> { + JavalinTest.test(TestUtils.createServer(), (server, client) -> { Response response = client.get("/v2/versions"); assertEquals(200, response.code()); String body = response.body().string(); diff --git a/src/test/java/net/fabricmc/meta/test/unit/ServerBootstrapTests.java b/src/test/java/net/fabricmc/meta/test/unit/ServerBootstrapTests.java index 91bb015..261f45a 100644 --- a/src/test/java/net/fabricmc/meta/test/unit/ServerBootstrapTests.java +++ b/src/test/java/net/fabricmc/meta/test/unit/ServerBootstrapTests.java @@ -29,7 +29,7 @@ import org.junit.jupiter.api.io.TempDir; import net.fabricmc.meta.FabricMeta; -import net.fabricmc.meta.web.WebServer; +import net.fabricmc.meta.test.TestUtils; public class ServerBootstrapTests { @TempDir @@ -43,7 +43,7 @@ static void beforeAll() { @Test void serverJar() { - JavalinTest.test(WebServer.create(), (server, client) -> { + JavalinTest.test(TestUtils.createServer(), (server, client) -> { Response response = client.get("/v2/versions/loader/stable/stable/stable/server/jar"); assertEquals(200, response.code()); Path jarFile = tempDir.resolve("server.jar"); From 3556d033949f8a56f9cf7e38122699250aa5b5d2 Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sun, 17 Dec 2023 10:31:30 +0000 Subject: [PATCH 3/4] Add basic caching layer. --- .../java/net/fabricmc/meta/FabricMeta.java | 5 +- .../net/fabricmc/meta/web/CacheHandler.java | 90 +++++++++++++++++++ .../java/net/fabricmc/meta/web/WebServer.java | 10 ++- .../net/fabricmc/meta/web/v1/ModelsV1.java | 17 ++-- .../net/fabricmc/meta/test/TestUtils.java | 4 +- 5 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 src/main/java/net/fabricmc/meta/web/CacheHandler.java diff --git a/src/main/java/net/fabricmc/meta/FabricMeta.java b/src/main/java/net/fabricmc/meta/FabricMeta.java index 68d6771..8fb8aba 100644 --- a/src/main/java/net/fabricmc/meta/FabricMeta.java +++ b/src/main/java/net/fabricmc/meta/FabricMeta.java @@ -35,6 +35,7 @@ import net.fabricmc.meta.data.VersionDatabase; import net.fabricmc.meta.utils.Reference; +import net.fabricmc.meta.web.CacheHandler; import net.fabricmc.meta.web.WebServer; public class FabricMeta { @@ -46,6 +47,7 @@ public class FabricMeta { private static final Map config = new HashMap<>(); private static boolean configInitialized; private static URL heartbeatUrl; // URL pinged with every successful update() + private static CacheHandler cacheHandler = new CacheHandler(); public static void main(String[] args) { Path configFile = Paths.get("config.json"); @@ -79,13 +81,14 @@ public static void main(String[] args) { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); executorService.scheduleAtFixedRate(FabricMeta::update, 1, 1, TimeUnit.MINUTES); - WebServer webServer = new WebServer(() -> database); + WebServer webServer = new WebServer(() -> database, cacheHandler); webServer.createServer().start(5555); } private static void update() { try { database = VersionDatabase.generate(); + cacheHandler.invalidateCache(); updateHeartbeat(); } catch (Throwable t) { if (database == null) { diff --git a/src/main/java/net/fabricmc/meta/web/CacheHandler.java b/src/main/java/net/fabricmc/meta/web/CacheHandler.java new file mode 100644 index 0000000..4774a1d --- /dev/null +++ b/src/main/java/net/fabricmc/meta/web/CacheHandler.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.meta.web; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import io.javalin.http.Handler; +import io.javalin.http.servlet.JavalinServletContext; + +public class CacheHandler { + private final Map cache = new ConcurrentHashMap<>(); + + public CacheHandler() { + } + + public Handler before() { + return ctx -> { + Response response = cache.get(ctx.path()); + + if (response == null) { + return; + } + + // Replay the response + ctx.status(response.status()); + response.headers().forEach(ctx::header); + ctx.contentType(response.contentType()); + ctx.result(response.body()); + + // Replace with ctx.skipRemainingHandlers() in Javalin 6 + JavalinServletContext jsc = (JavalinServletContext) ctx; + jsc.getTasks().clear(); + }; + } + + public Handler after() { + return ctx -> { + if (ctx.statusCode() != 200) { + return; + } + + if (!ctx.queryParamMap().isEmpty()) { + // Don't cache any requests with query params to prevent the cache from growing too big. + // Maybe look into something better here + return; + } + + cache.put(ctx.path(), new Response( + ctx.statusCode(), + readAllBytes(ctx.resultInputStream()), + ctx.headerMap(), + ctx.res().getContentType())); + }; + } + + private static byte[] readAllBytes(InputStream is) throws IOException { + is.reset(); + byte[] bytes = is.readAllBytes(); + is.reset(); + return bytes; + } + + public void invalidateCache() { + cache.clear(); + } + + private record Response( + int status, + byte[] body, + Map headers, + String contentType) { + } +} diff --git a/src/main/java/net/fabricmc/meta/web/WebServer.java b/src/main/java/net/fabricmc/meta/web/WebServer.java index 03fd248..7c38f75 100644 --- a/src/main/java/net/fabricmc/meta/web/WebServer.java +++ b/src/main/java/net/fabricmc/meta/web/WebServer.java @@ -16,6 +16,8 @@ package net.fabricmc.meta.web; +import static io.javalin.apibuilder.ApiBuilder.after; +import static io.javalin.apibuilder.ApiBuilder.before; import static io.javalin.apibuilder.ApiBuilder.path; import java.util.function.Function; @@ -39,10 +41,14 @@ public class WebServer { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private final DataProvider dataProvider; + private final CacheHandler cacheHandler; + private final EndpointsV1 endpointsV1; - public WebServer(DataProvider dataProvider) { + public WebServer(DataProvider dataProvider, CacheHandler cacheHandler) { this.dataProvider = dataProvider; + this.cacheHandler = cacheHandler; + endpointsV1 = new EndpointsV1(dataProvider); } @@ -52,6 +58,8 @@ public Javalin createServer() { config.showJavalinBanner = false; config.plugins.enableCors(cors -> cors.add(CorsPluginConfig::anyHost)); }).routes(() -> { + before(cacheHandler.before()); + after(cacheHandler.after()); path("v1", endpointsV1.routes()); }); diff --git a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java index c6d7975..d8b9888 100644 --- a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java +++ b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java @@ -31,13 +31,14 @@ import net.fabricmc.meta.web.JsonModel; /** - * Strongly defined records of the public API. Take extra care to record to method return types here. + * Strongly defined records of the public API. Take extra care when changing method return types and record components. */ public sealed interface ModelsV1 extends JsonModel permits ModelsV1.GameVersion, ModelsV1.MappingVersion, ModelsV1.LoaderVersion, ModelsV1.LoaderInfo, ModelsV1.LoaderLauncherInfo { /** - * /v2/versions/game + * /v1/versions/game */ static List gameVersions(DataProvider dataProvider) { + System.out.println("ohno"); LinkedList versions = new LinkedList<>(); for (BaseVersion version : dataProvider.getGameVersions()) { @@ -48,7 +49,7 @@ static List gameVersions(DataProvider dataProvider) { } /** - * /v2/game/{game_version} + * /v1/game/{game_version} */ static List gameVersions(DataProvider dataProvider, String gameVersion) { for (BaseVersion version : dataProvider.getGameVersions()) { @@ -61,7 +62,7 @@ static List gameVersions(DataProvider dataProvider, String gameVers } /** - * /v2/versions/mappings + * /v1/versions/mappings */ static List mappingVersions(DataProvider dataProvider) { LinkedList versions = new LinkedList<>(); @@ -74,7 +75,7 @@ static List mappingVersions(DataProvider dataProvider) { } /** - * /v2/mappings/{game_version} + * /v1/mappings/{game_version} */ static List mappingVersions(DataProvider dataProvider, String gameVersion) { LinkedList versions = new LinkedList<>(); @@ -89,7 +90,7 @@ static List mappingVersions(DataProvider dataProvider, String ga } /** - * /v2/versions/loader + * /v1/versions/loader */ static List loaderVersions(DataProvider dataProvider) { LinkedList versions = new LinkedList<>(); @@ -102,7 +103,7 @@ static List loaderVersions(DataProvider dataProvider) { } /** - * /v2/versions/loader/{game_version}/{loader_version} + * /v1/versions/loader/{game_version}/{loader_version} */ static List loaderInfo(DataProvider dataProvider, String gameVersion) { MavenBuildGameVersion mappings = null; @@ -128,7 +129,7 @@ static List loaderInfo(DataProvider dataProvider, String gameVersion } /** - * /v2/versions/loader/{game_version}/{loader_version} + * /v1/versions/loader/{game_version}/{loader_version} */ static LoaderLauncherInfo loaderLauncherInfo(DataProvider dataProvider, String gameVersion, String loaderVersion) { MavenBuildVersion loader = null; diff --git a/src/test/java/net/fabricmc/meta/test/TestUtils.java b/src/test/java/net/fabricmc/meta/test/TestUtils.java index ee97998..573a113 100644 --- a/src/test/java/net/fabricmc/meta/test/TestUtils.java +++ b/src/test/java/net/fabricmc/meta/test/TestUtils.java @@ -19,10 +19,12 @@ import io.javalin.Javalin; import net.fabricmc.meta.FabricMeta; +import net.fabricmc.meta.web.CacheHandler; import net.fabricmc.meta.web.WebServer; public class TestUtils { public static Javalin createServer() { - return new WebServer(() -> FabricMeta.database).createServer(); + CacheHandler cacheHandler = new CacheHandler(); + return new WebServer(() -> FabricMeta.database, cacheHandler).createServer(); } } From 19ab7172e14b03a28f0923d193a0029155d62f6a Mon Sep 17 00:00:00 2001 From: modmuss50 Date: Sun, 17 Dec 2023 10:49:53 +0000 Subject: [PATCH 4/4] Update to javalin 6 beta --- build.gradle | 4 ++-- .../net/fabricmc/meta/web/CacheHandler.java | 5 +---- .../java/net/fabricmc/meta/web/WebServer.java | 17 +++++++++++------ .../java/net/fabricmc/meta/web/v1/ModelsV1.java | 1 - 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index b01ff76..f406e39 100644 --- a/build.gradle +++ b/build.gradle @@ -22,14 +22,14 @@ repositories { dependencies { implementation 'com.google.code.gson:gson:2.10.1' - implementation 'io.javalin:javalin:5.6.3' + implementation 'io.javalin:javalin:6.0.0-beta.3' implementation 'org.slf4j:slf4j-simple:2.0.9' implementation 'commons-io:commons-io:2.15.1' implementation 'org.jetbrains:annotations:24.1.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' testImplementation "org.junit.jupiter:junit-jupiter-params:5.9.2" - testImplementation 'io.javalin:javalin-testtools:5.6.3' + testImplementation 'io.javalin:javalin-testtools:6.0.0-beta.3' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/src/main/java/net/fabricmc/meta/web/CacheHandler.java b/src/main/java/net/fabricmc/meta/web/CacheHandler.java index 4774a1d..29510cb 100644 --- a/src/main/java/net/fabricmc/meta/web/CacheHandler.java +++ b/src/main/java/net/fabricmc/meta/web/CacheHandler.java @@ -22,7 +22,6 @@ import java.util.concurrent.ConcurrentHashMap; import io.javalin.http.Handler; -import io.javalin.http.servlet.JavalinServletContext; public class CacheHandler { private final Map cache = new ConcurrentHashMap<>(); @@ -44,9 +43,7 @@ public Handler before() { ctx.contentType(response.contentType()); ctx.result(response.body()); - // Replace with ctx.skipRemainingHandlers() in Javalin 6 - JavalinServletContext jsc = (JavalinServletContext) ctx; - jsc.getTasks().clear(); + ctx.skipRemainingHandlers(); }; } diff --git a/src/main/java/net/fabricmc/meta/web/WebServer.java b/src/main/java/net/fabricmc/meta/web/WebServer.java index 7c38f75..d2a535d 100644 --- a/src/main/java/net/fabricmc/meta/web/WebServer.java +++ b/src/main/java/net/fabricmc/meta/web/WebServer.java @@ -28,7 +28,9 @@ import io.javalin.Javalin; import io.javalin.http.Context; import io.javalin.http.Header; +import io.javalin.plugin.bundled.CorsPlugin; import io.javalin.plugin.bundled.CorsPluginConfig; +import io.javalin.plugin.bundled.RouteOverviewPlugin; import net.fabricmc.meta.data.DataProvider; import net.fabricmc.meta.web.v1.EndpointsV1; @@ -54,13 +56,16 @@ public WebServer(DataProvider dataProvider, CacheHandler cacheHandler) { public Javalin createServer() { Javalin javalin = Javalin.create(config -> { - config.plugins.enableRouteOverview("/"); + config.useVirtualThreads = true; config.showJavalinBanner = false; - config.plugins.enableCors(cors -> cors.add(CorsPluginConfig::anyHost)); - }).routes(() -> { - before(cacheHandler.before()); - after(cacheHandler.after()); - path("v1", endpointsV1.routes()); + config.registerPlugin(new RouteOverviewPlugin(routeOverview -> routeOverview.path = "/")); + config.registerPlugin(new CorsPlugin(cors -> cors.addRule(CorsPluginConfig.CorsRule::anyHost))); + + config.router.apiBuilder(() -> { + before(cacheHandler.before()); + after(cacheHandler.after()); + path("v1", endpointsV1.routes()); + }); }); // TODO remove this diff --git a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java index d8b9888..046a236 100644 --- a/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java +++ b/src/main/java/net/fabricmc/meta/web/v1/ModelsV1.java @@ -38,7 +38,6 @@ public sealed interface ModelsV1 extends JsonModel permits ModelsV1.GameVersion, * /v1/versions/game */ static List gameVersions(DataProvider dataProvider) { - System.out.println("ohno"); LinkedList versions = new LinkedList<>(); for (BaseVersion version : dataProvider.getGameVersions()) {