feature/undertow #4
9 changed files with 142 additions and 206 deletions
2
pom.xml
2
pom.xml
|
@ -52,7 +52,7 @@
|
|||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
<version>2.2.22.Final</version>
|
||||
<version>2.3.5.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
|
|
|
@ -1,48 +1,51 @@
|
|||
package ch.fritteli.labyrinth.server;
|
||||
|
||||
import ch.fritteli.labyrinth.server.handler.CreateHandler;
|
||||
import ch.fritteli.labyrinth.server.handler.LanyrinthRenderHandler;
|
||||
import ch.fritteli.labyrinth.server.handler.RenderHandler;
|
||||
import io.undertow.Undertow;
|
||||
import io.undertow.server.RoutingHandler;
|
||||
import io.undertow.util.StatusCodes;
|
||||
import io.vavr.control.Try;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
@Slf4j
|
||||
public class LabyrinthServer {
|
||||
@NonNull
|
||||
private final ServerConfig config;
|
||||
@NonNull
|
||||
private final Undertow undertow;
|
||||
|
||||
private LabyrinthServer(@NonNull final ServerConfig config) {
|
||||
log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort());
|
||||
final RoutingHandler routingHandler = new RoutingHandler().get(CreateHandler.PATH_TEMPLATE, new CreateHandler())
|
||||
.post("/render", new LanyrinthRenderHandler())
|
||||
.setFallbackHandler(exchange -> exchange.setStatusCode(
|
||||
StatusCodes.NOT_FOUND)
|
||||
.getResponseSender()
|
||||
.send("Resource %s not found".formatted(
|
||||
exchange.getRequestURI())));
|
||||
this.config = config;
|
||||
final String hostAddress = config.getAddress().getHostAddress();
|
||||
final int port = config.getPort();
|
||||
log.info("Starting Server at http://{}:{}/", hostAddress, port);
|
||||
final RoutingHandler routingHandler = new RoutingHandler()
|
||||
.get(CreateHandler.PATH_TEMPLATE, new CreateHandler())
|
||||
.post("/render", new RenderHandler());
|
||||
|
||||
this.undertow = Undertow.builder()
|
||||
.addHttpListener(config.getPort(), config.getAddress().getHostAddress())
|
||||
.addHttpListener(port, hostAddress)
|
||||
.setHandler(routingHandler)
|
||||
.build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Try<LabyrinthServer> createAndStartServer() {
|
||||
final Try<LabyrinthServer> serverOption = Try.of(ServerConfig::init).mapTry(LabyrinthServer::new);
|
||||
serverOption.forEach(LabyrinthServer::start);
|
||||
return serverOption;
|
||||
return Try.of(ServerConfig::init)
|
||||
.flatMapTry(LabyrinthServer::createAndStartServer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Try<LabyrinthServer> createAndStartServer(@NonNull final ServerConfig config) {
|
||||
return Try.of(() -> new LabyrinthServer(config))
|
||||
.peek(LabyrinthServer::start);
|
||||
}
|
||||
|
||||
private void start() {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper"));
|
||||
this.undertow.start();
|
||||
Try.of(() -> (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress())
|
||||
.onFailure(e -> log.warn("Started server, unable to determine listeing address/port."))
|
||||
.forEach(address -> log.info("Listening on http://{}:{}", address.getHostString(), address.getPort()));
|
||||
log.info("Listeing on http://{}:{}", this.config.getAddress().getHostAddress(), this.config.getPort());
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
|
@ -51,110 +54,6 @@ public class LabyrinthServer {
|
|||
log.info("Server stopped.");
|
||||
}
|
||||
|
||||
// private void handleCreate(HttpExchange exchange) {
|
||||
// this.executorService.submit(() -> {
|
||||
// log.debug("Handling request to {}", exchange.getRequestURI());
|
||||
// try {
|
||||
// final String requestMethod = exchange.getRequestMethod();
|
||||
// if (!requestMethod.equals("GET")) {
|
||||
// exchange.getResponseBody().close();
|
||||
// exchange.sendResponseHeaders(405, -1);
|
||||
// return;
|
||||
// }
|
||||
// final Map<RequestParameter, String> requestParams = this.parseQueryString(exchange.getRequestURI()
|
||||
// .getQuery());
|
||||
// final int width = this.getOrDefault(requestParams.get(RequestParameter.WIDTH), Integer::valueOf, 5);
|
||||
// final int height = this.getOrDefault(requestParams.get(RequestParameter.HEIGHT), Integer::valueOf, 7);
|
||||
// final Option<Long> idOption = requestParams.get(RequestParameter.ID)
|
||||
// .toTry()
|
||||
// .map(Long::valueOf)
|
||||
// .toOption();
|
||||
// final Option<OutputType> outputOption = requestParams.get(RequestParameter.OUTPUT)
|
||||
// .flatMap(OutputType::ofString);
|
||||
// final Headers responseHeaders = exchange.getResponseHeaders();
|
||||
// final AtomicBoolean needsRedirect = new AtomicBoolean(false);
|
||||
// final long id = idOption.onEmpty(() -> needsRedirect.set(true)).getOrElse(System::nanoTime);
|
||||
// final OutputType output = outputOption.onEmpty(() -> needsRedirect.set(true))
|
||||
// .getOrElse(OutputType.HTML);
|
||||
// if (needsRedirect.get()) {
|
||||
// responseHeaders.add("Location",
|
||||
// "create?width=" + width + "&height=" + height + "&output=" + output
|
||||
// .toString() +
|
||||
// "&id=" + id
|
||||
// );
|
||||
// exchange.sendResponseHeaders(302, -1);
|
||||
// return;
|
||||
// }
|
||||
// final byte[] render;
|
||||
// try {
|
||||
// final Labyrinth labyrinth = new Labyrinth(width, height, id);
|
||||
// render = output.render(labyrinth);
|
||||
// } catch (Exception e) {
|
||||
// responseHeaders.add("Content-type", "text/plain; charset=UTF-8");
|
||||
// exchange.sendResponseHeaders(500, 0);
|
||||
// final OutputStream responseBody = exchange.getResponseBody();
|
||||
// responseBody.write(("Error: " + e.getMessage()).getBytes(StandardCharsets.UTF_8));
|
||||
// responseBody.flush();
|
||||
// return;
|
||||
// }
|
||||
// responseHeaders.add("Content-type", output.getContentType());
|
||||
// if (output.isAttachment()) {
|
||||
// responseHeaders.add("Content-disposition", String.format(
|
||||
// "attachment; filename=\"labyrinth-%dx%d-%d.%s\"",
|
||||
// width,
|
||||
// height,
|
||||
// id,
|
||||
// output.getFileExtension()
|
||||
// ));
|
||||
// }
|
||||
// exchange.sendResponseHeaders(200, 0);
|
||||
// final OutputStream responseBody = exchange.getResponseBody();
|
||||
// responseBody.write(render);
|
||||
// responseBody.flush();
|
||||
// } catch (Exception e) {
|
||||
// log.error("FSCK!", e);
|
||||
// } finally {
|
||||
// exchange.close();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// @NonNull
|
||||
// private Map<RequestParameter, String> parseQueryString(@Nullable final String query) {
|
||||
// if (query == null) {
|
||||
// return HashMap.empty();
|
||||
// }
|
||||
// HashMap<RequestParameter, String> result = HashMap.empty();
|
||||
// final String[] parts = query.split("&");
|
||||
// for (final String part : parts) {
|
||||
// final int split = part.indexOf('=');
|
||||
// if (split == -1) {
|
||||
// final Try<RequestParameter> tryKey = Try.of(() -> this.normalizeParameterName(part));
|
||||
// if (tryKey.isSuccess()) {
|
||||
// result = result.put(tryKey.get(), null);
|
||||
// }
|
||||
// } else {
|
||||
// final String key = part.substring(0, split);
|
||||
// final String value = part.substring(split + 1);
|
||||
// final Try<RequestParameter> tryKey = Try.of(() -> this.normalizeParameterName(key));
|
||||
// if (tryKey.isSuccess()) {
|
||||
// result = result.put(tryKey.get(), value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// private RequestParameter normalizeParameterName(final String paramName) {
|
||||
// return RequestParameter.parseName(paramName).get();
|
||||
// }
|
||||
|
||||
// private <T> T getOrDefault(@NonNull final Option<String> input,
|
||||
// @NonNull final Function<String, T> mapper,
|
||||
// @Nullable final T defaultValue) {
|
||||
// return input.toTry().map(mapper).getOrElse(defaultValue);
|
||||
// }
|
||||
|
||||
// private void handleRender(final HttpExchange exchange) {
|
||||
// this.executorService.submit(() -> {
|
||||
// try {
|
||||
|
@ -198,23 +97,4 @@ public class LabyrinthServer {
|
|||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// private enum RequestParameter {
|
||||
// WIDTH("w", "width"),
|
||||
// HEIGHT("h", "height"),
|
||||
// ID("i", "id"),
|
||||
// OUTPUT("o", "output");
|
||||
// private final Set<String> names;
|
||||
//
|
||||
// RequestParameter(@NonNull final String... names) {
|
||||
// this.names = HashSet.of(names);
|
||||
// }
|
||||
//
|
||||
// static Option<RequestParameter> parseName(@Nullable final String name) {
|
||||
// if (name == null) {
|
||||
// return Option.none();
|
||||
// }
|
||||
// return Stream.of(values()).find(param -> param.names.exists(name::equalsIgnoreCase));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
LabyrinthServer.createAndStartServer().onFailure(e -> log.error("Failed to create server. Stopping.", e));
|
||||
LabyrinthServer.createAndStartServer()
|
||||
.onFailure(e -> log.error("Failed to create server. Stopping.", e));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,38 +17,51 @@ import java.util.function.Function;
|
|||
|
||||
public enum OutputType {
|
||||
TEXT_PLAIN("text/plain; charset=UTF-8",
|
||||
labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8),
|
||||
"txt",
|
||||
labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8),
|
||||
false,
|
||||
"t",
|
||||
"text"
|
||||
),
|
||||
"text"),
|
||||
HTML("text/html",
|
||||
labyrinth -> HTMLRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8),
|
||||
"html",
|
||||
labyrinth -> HTMLRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8),
|
||||
false,
|
||||
"h",
|
||||
"html"
|
||||
),
|
||||
PDF("application/pdf", labyrinth -> PDFRenderer.newInstance().render(labyrinth), "pdf", false, "p", "pdf"),
|
||||
PDFFILE("application/pdf", labyrinth -> PDFRenderer.newInstance().render(labyrinth), "pdf", true, "f", "pdffile"),
|
||||
BINARY("application/octet-stream", SerializerDeserializer::serialize, "laby", true, "b", "binary");
|
||||
"html"),
|
||||
PDF("application/pdf",
|
||||
"pdf",
|
||||
labyrinth -> PDFRenderer.newInstance().render(labyrinth),
|
||||
false,
|
||||
"p",
|
||||
"pdf"),
|
||||
PDFFILE("application/pdf",
|
||||
"pdf",
|
||||
labyrinth -> PDFRenderer.newInstance().render(labyrinth),
|
||||
true,
|
||||
"f",
|
||||
"pdffile"),
|
||||
BINARY("application/octet-stream",
|
||||
"laby",
|
||||
SerializerDeserializer::serialize,
|
||||
true,
|
||||
"b",
|
||||
"binary");
|
||||
@Getter
|
||||
@NonNull
|
||||
private final String contentType;
|
||||
@Getter
|
||||
@NonNull
|
||||
private final List<String> names;
|
||||
private final String fileExtension;
|
||||
@NonNull
|
||||
private final Function<Labyrinth, byte[]> render;
|
||||
@Getter
|
||||
private final boolean attachment;
|
||||
@Getter
|
||||
@NonNull
|
||||
private final String fileExtension;
|
||||
private final List<String> names;
|
||||
|
||||
OutputType(@NonNull final String contentType,
|
||||
@NonNull final Function<Labyrinth, byte[]> render,
|
||||
@NonNull final String fileExtension,
|
||||
@NonNull final Function<Labyrinth, byte[]> render,
|
||||
final boolean attachment,
|
||||
@NonNull final String... names) {
|
||||
this.contentType = contentType;
|
||||
|
@ -58,20 +71,23 @@ public enum OutputType {
|
|||
this.names = List.of(names);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Option<OutputType> ofString(@Nullable final String name) {
|
||||
if (name == null) {
|
||||
return Option.none();
|
||||
}
|
||||
final String nameLC = name.toLowerCase();
|
||||
return Stream.of(values()).find(param -> param.names.contains(nameLC));
|
||||
return Option.of(name)
|
||||
.map(String::toLowerCase)
|
||||
.flatMap(nameLC -> Stream.of(values())
|
||||
.find(param -> param.names.contains(nameLC)));
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.names.last();
|
||||
}
|
||||
|
||||
public byte[] render(@NonNull final Labyrinth labyrinth) {
|
||||
@NonNull
|
||||
public byte[] render(@NonNull final Labyrinth labyrinth) throws Exception {
|
||||
return this.render.apply(labyrinth);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,8 @@ public class ServerConfig {
|
|||
public static final String SYSPROP_HOST = "fritteli.labyrinth.server.host";
|
||||
public static final String SYSPROP_PORT = "fritteli.labyrinth.server.port";
|
||||
|
||||
@NonNull InetAddress address;
|
||||
@NonNull
|
||||
InetAddress address;
|
||||
int port;
|
||||
|
||||
public ServerConfig(@Nullable final String address, final int port) throws ConfigurationException {
|
||||
|
@ -26,19 +27,6 @@ public class ServerConfig {
|
|||
log.debug("host={}, port={}", this.address, this.port);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static InetAddress validateAddress(@Nullable final String address) {
|
||||
return Try.of(() -> InetAddress.getByName(address))
|
||||
.getOrElseThrow(cause -> new ConfigurationException("Invalid hostname/address: " + address, cause));
|
||||
}
|
||||
|
||||
private static int validatePort(final int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new ConfigurationException("Port out of range (0..65535): " + port);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ServerConfig init() throws ConfigurationException {
|
||||
final String host = System.getProperty(SYSPROP_HOST);
|
||||
|
@ -47,15 +35,30 @@ public class ServerConfig {
|
|||
return new ServerConfig(host, port);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static InetAddress validateAddress(@Nullable final String address) {
|
||||
return Try.of(() -> InetAddress.getByName(address))
|
||||
.getOrElseThrow(cause -> new ConfigurationException(
|
||||
"Invalid hostname/address: %s".formatted(address),
|
||||
cause
|
||||
));
|
||||
}
|
||||
|
||||
private static int validatePort(final int port) {
|
||||
if (port < 0 || port > 0xFFFF) {
|
||||
throw new ConfigurationException("Port out of range (0..65535): %s".formatted(port));
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
private static int validatePort(@Nullable final String portString) {
|
||||
if (portString == null) {
|
||||
log.info("No port configured; using default.");
|
||||
return 0;
|
||||
}
|
||||
return Try.of(() -> Integer.valueOf(portString))
|
||||
.map(ServerConfig::validatePort)
|
||||
.getOrElseThrow(cause -> new ConfigurationException(
|
||||
"Failed to parse port specified in system property '" + SYSPROP_PORT + "': " + portString,
|
||||
"Failed to parse port specified in system property '%s': %s".formatted(SYSPROP_PORT, portString),
|
||||
cause
|
||||
));
|
||||
}
|
||||
|
|
|
@ -5,22 +5,28 @@ import io.undertow.server.HttpServerExchange;
|
|||
import io.undertow.util.StatusCodes;
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AbstractHttpHandler implements HttpHandler {
|
||||
@Override
|
||||
public final void handleRequest(final HttpServerExchange exchange) {
|
||||
if (exchange.isInIoThread()) {
|
||||
exchange.dispatch(this);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.handle(exchange);
|
||||
} catch (@NonNull final Exception e) {
|
||||
log.error("Error handling request", e);
|
||||
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
|
||||
.getResponseSender()
|
||||
.send(StatusCodes.INTERNAL_SERVER_ERROR_STRING);
|
||||
public final void handleRequest(@NonNull final HttpServerExchange exchange) {
|
||||
try (final MDC.MDCCloseable mdc = MDC.putCloseable("correlationId", UUID.randomUUID().toString())) {
|
||||
if (exchange.isInIoThread()) {
|
||||
log.debug("Dispatching request");
|
||||
exchange.dispatch(this);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.handle(exchange);
|
||||
} catch (@NonNull final Exception e) {
|
||||
log.error("Error handling request", e);
|
||||
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
|
||||
.getResponseSender()
|
||||
.send(StatusCodes.INTERNAL_SERVER_ERROR_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,15 @@ import io.vavr.control.Try;
|
|||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Deque;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
public class CreateHandler extends AbstractHttpHandler {
|
||||
|
@ -26,19 +30,34 @@ public class CreateHandler extends AbstractHttpHandler {
|
|||
|
||||
@Override
|
||||
protected void handle(@NonNull final HttpServerExchange exchange) {
|
||||
final Instant start = Instant.now();
|
||||
log.debug("Handling create request");
|
||||
this.createLabyrinthFromRequestParameters(exchange.getQueryParameters())
|
||||
.onFailure(e -> {
|
||||
log.error("Error creating Labyrinth from request", e);
|
||||
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
|
||||
exchange.setReasonPhrase(e.getMessage());
|
||||
}).forEach(tuple -> {
|
||||
exchange.setReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR_STRING);
|
||||
})
|
||||
.forEach(tuple -> {
|
||||
final OutputType outputType = tuple._1();
|
||||
final Labyrinth labyrinth = tuple._2();
|
||||
final byte[] bytes = outputType.render(labyrinth);
|
||||
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, outputType.getContentType());
|
||||
exchange.getResponseHeaders().put(HttpString.tryFromString("X-Labyrinth-ID"), String.valueOf(labyrinth.getRandomSeed()));
|
||||
exchange.getResponseHeaders().put(HttpString.tryFromString("X-Labyrinth-Width"), String.valueOf(labyrinth.getWidth()));
|
||||
exchange.getResponseHeaders().put(HttpString.tryFromString("X-Labyrinth-Height"), String.valueOf(labyrinth.getHeight()));
|
||||
final byte[] bytes;
|
||||
try {
|
||||
bytes = outputType.render(labyrinth);
|
||||
} catch (@NonNull final Exception e) {
|
||||
log.error("Error rendering Labyrinth", e);
|
||||
exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
|
||||
exchange.setReasonPhrase(StatusCodes.INTERNAL_SERVER_ERROR_STRING);
|
||||
return;
|
||||
}
|
||||
exchange.getResponseHeaders()
|
||||
.put(Headers.CONTENT_TYPE, outputType.getContentType())
|
||||
.put(HttpString.tryFromString("X-Labyrinth-ID"), String.valueOf(labyrinth.getRandomSeed()))
|
||||
.put(HttpString.tryFromString("X-Labyrinth-Width"), String.valueOf(labyrinth.getWidth()))
|
||||
.put(HttpString.tryFromString("X-Labyrinth-Height"), String.valueOf(labyrinth.getHeight()))
|
||||
.put(HttpString.tryFromString("X-Labyrinth-Generation-Duration-millis"), String.valueOf(start.until(Instant.now(), ChronoUnit.MILLIS)));
|
||||
exchange.getResponseSender().send(ByteBuffer.wrap(bytes));
|
||||
log.debug("Create request handled.");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -73,13 +92,24 @@ public class CreateHandler extends AbstractHttpHandler {
|
|||
});
|
||||
}
|
||||
|
||||
@NonNull Try<Tuple2<OutputType, Labyrinth>> createLabyrinth() {
|
||||
final Option<OutputType> output = getParameterValues(RequestParameter.OUTPUT).foldLeft(Option.none(), (type, param) -> type.orElse(() -> OutputType.ofString(param)));
|
||||
final Option<Integer> width = getParameterValues(RequestParameter.WIDTH).foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Integer.parseInt(param)).toOption()));
|
||||
final Option<Integer> height = getParameterValues(RequestParameter.HEIGHT).foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Integer.parseInt(param)).toOption()));
|
||||
final Option<Long> id = getParameterValues(RequestParameter.ID).foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Long.parseLong(param)).toOption()));
|
||||
@NonNull
|
||||
Try<Tuple2<OutputType, Labyrinth>> createLabyrinth() {
|
||||
final Option<OutputType> output = getParameterValues(RequestParameter.OUTPUT)
|
||||
.foldLeft(Option.none(), (type, param) -> type.orElse(() -> OutputType.ofString(param)));
|
||||
final Option<Integer> width = getParameterValues(RequestParameter.WIDTH)
|
||||
.foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Integer.parseInt(param)).toOption()));
|
||||
final Option<Integer> height = getParameterValues(RequestParameter.HEIGHT)
|
||||
.foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Integer.parseInt(param)).toOption()));
|
||||
final Option<Long> id = getParameterValues(RequestParameter.ID)
|
||||
.foldLeft(Option.none(), (value, param) -> value.orElse(() -> Try.of(() -> Long.parseLong(param)).toOption()));
|
||||
|
||||
return Try.of(() -> Tuple.of(output.get(), new Labyrinth(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()))));
|
||||
return Try.of(() -> {
|
||||
final OutputType t1 = output.get();
|
||||
final Integer width1 = width.get();
|
||||
final Integer height1 = height.get();
|
||||
final Long orElse = id.getOrElse(() -> new Random().nextLong());
|
||||
return Tuple.of(t1, new Labyrinth(width1, height1, orElse));
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
|
@ -4,7 +4,7 @@ import io.undertow.server.HttpHandler;
|
|||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.StatusCodes;
|
||||
|
||||
public class LanyrinthRenderHandler implements HttpHandler {
|
||||
public class RenderHandler implements HttpHandler {
|
||||
@Override
|
||||
public void handleRequest(final HttpServerExchange exchange) {
|
||||
if (exchange.isInIoThread()) {
|
|
@ -6,7 +6,7 @@
|
|||
<!-- encoders are by default assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<pattern>%d{HH:mm:ss.SSS} %-5level %X{correlationId} [%thread] %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
|
|
Loading…
Reference in a new issue