package xyz.etztech.serverapi.web; import io.javalin.Javalin; import io.javalin.core.event.EventListener; import io.javalin.core.plugin.Plugin; import io.javalin.core.util.RouteOverviewPlugin; import io.javalin.http.Context; import io.javalin.http.UnauthorizedResponse; import io.javalin.plugin.graphql.GraphQLOptions; import io.javalin.plugin.graphql.GraphQLPlugin; import io.javalin.plugin.json.JavalinJson; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.helpers.NOPLogger; import xyz.etztech.serverapi.ServerAPI; import xyz.etztech.serverapi.web.api.ErrorAPI; public class Web { private final IProvider provider; private String password; private Javalin app; public Web(IProvider provider) { this.provider = provider; } public void start(int port, String password) { Javalin.log = NOPLogger.NOP_LOGGER; app = Javalin.create(config -> { config.registerPlugin(graphql()); config.registerPlugin(new RouteOverviewPlugin("/")); config.enableCorsForAllOrigins(); }).events(this::events).exception(Exception.class, this::exception); this.password = password; if (!"".equals(password)) { app.before(this::access); } app.get("/bans", this::bans); app.get("/players", this::players); app.get("/query", this::query); app.get("/tps", this::tps); app.get("/worlds", this::worlds); app.get("/worlds/:name", this::world); // What in the actual fuck... https://github.com/tipsy/javalin/issues/358 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(ServerAPI.class.getClassLoader()); app.start(port); Thread.currentThread().setContextClassLoader(classLoader); } public void stop() { if (app != null) { app.stop(); } } public void events(EventListener event) { event.serverStarting(() -> provider.log("Starting API...")); event.serverStarted(() -> provider.log("API is ready!")); event.serverStartFailed(() -> provider.log("Could not start API...")); event.serverStopping(() -> provider.log("Stopping API...")); event.serverStopped(() -> provider.log("API is stopped!")); } public void exception(Exception exception, Context ctx) { provider.log(String.format("API Exception at %s:\n%s", ctx.req.getRequestURI(), ExceptionUtils.getStackTrace(exception))); ctx.status(500); ctx.json(new ErrorAPI(500, "Internal Error")); } public void access(Context ctx) { String pw = ctx.header("X-ServerAPI-Password"); if (pw == null) { pw = ctx.queryParam("password"); } if (!password.equals(pw)) { throw new UnauthorizedResponse(JavalinJson.toJson(new ErrorAPI(401, "Unauthorized"))); } } public Plugin graphql() { GraphQLOptions options = new GraphQLOptions("/graphql", null) .addPackage("xyz.etztech.serverapi.web.api") .register(new GraphQL(provider)); return new GraphQLPlugin(options); } public void tps(Context ctx) { ctx.json(provider.TPS()); } public void worlds(Context ctx) { ctx.json(provider.worlds()); } public void world(Context ctx) { ctx.json(provider.world(ctx.pathParam("name"))); } public void players(Context ctx) { ctx.json(provider.players()); } public void bans(Context ctx) { ctx.json(provider.bans()); } public void query(Context ctx) { ctx.json(provider.query()); } }