package cz.senslog.analyzer.ws.vertx; import cz.senslog.analyzer.ws.Server; import cz.senslog.analyzer.ws.handler.GroupsHandler; import cz.senslog.analyzer.ws.handler.InfoHandler; import cz.senslog.analyzer.ws.handler.StatisticsHandler; import io.vertx.core.*; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Router; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.inject.Inject; import java.util.HashMap; import java.util.Map; import static cz.senslog.analyzer.util.StringUtils.getOrDefault; import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE; public class VertxServer extends AbstractVerticle implements Server { private static final Logger logger = LogManager.getLogger(VertxServer.class); private final Map restHandlers; @Inject public VertxServer( InfoHandler infoHandler, StatisticsHandler statisticsHandler, GroupsHandler groupsHandler ) { this.restHandlers = new HashMap<>(); registerRestHandler("info", infoHandler); registerRestHandler("analytics", statisticsHandler); registerRestHandler("groups", groupsHandler); } private void registerRestHandler(String id, AbstractRestHandler handler) { id = id.charAt(0) == '/' ? id : "/" + id; restHandlers.put(id, handler); } @Override public void start(final Promise promise) { Router router = Router.router(vertx); router.route().handler(ctx -> { String origin = getOrDefault(ctx.request().getHeader("origin"), "*"); ctx.response().putHeader("Access-Control-Allow-Origin", origin); ctx.next(); }); for (Map.Entry handlerEntry : restHandlers.entrySet()) { router.route(handlerEntry.getKey()).subRouter(handlerEntry.getValue().start(vertx)); } router.route().failureHandler(ctx -> { logger.catching(ctx.failure()); HttpServerResponse response = ctx.response(); response.putHeader(CONTENT_TYPE, "application/json"); JsonObject error = new JsonObject() .put("timestamp", System.nanoTime()) .put("message", ctx.failure().getMessage()) .put("path", ctx.request().path()); int code = ctx.statusCode() > 0 ? ctx.statusCode() : 400; response.setStatusCode(code).end(error.encode()); }); vertx.createHttpServer() .requestHandler(router) .listen(config().getInteger("http.server.port"), result -> { if (result.succeeded()) { promise.complete(); } else { promise.fail(result.cause()); } }); } @Override public void stop() { this.vertx.close(); } @Override public void start(int port) { vertx = Vertx.vertx(); DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject() .put("http.server.port", port) ); vertx.deployVerticle(this, options, res -> { if (res.succeeded()) { logger.info("Deployment id is {} ", res.result()); logger.info("The HTTP server running on port {}.", port); } else { logger.error("Could not start the HTTP server: " + res.cause()); } }); } }