diff --git a/maven-settings.xml b/maven-settings.xml index adce7ab..18a15cb 100644 --- a/maven-settings.xml +++ b/maven-settings.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> -<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" - xmlns="http://maven.apache.org/SETTINGS/1.1.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <servers> - <server> - <id>repo.gittr.ch</id> - <username>ci</username> - <password>${env.REPO_TOKEN}</password> - </server> - </servers> +<settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" + xmlns="http://maven.apache.org/SETTINGS/1.1.0"> + <servers> + <server> + <id>repo.gittr.ch</id> + <username>ci</username> + <password>${env.REPO_TOKEN}</password> + </server> + </servers> </settings> diff --git a/pom.xml b/pom.xml index 8259a2d..f99aeac 100644 --- a/pom.xml +++ b/pom.xml @@ -1,130 +1,132 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>ch.fritteli</groupId> - <artifactId>fritteli-build-parent</artifactId> - <version>2.0.4</version> - </parent> + <parent> + <groupId>ch.fritteli</groupId> + <artifactId>fritteli-build-parent</artifactId> + <version>2.0.4</version> + </parent> - <groupId>ch.fritteli.labyrinth</groupId> - <artifactId>labyrinth-server</artifactId> - <version>0.0.2-SNAPSHOT</version> + <groupId>ch.fritteli.labyrinth</groupId> + <artifactId>labyrinth-server</artifactId> + <version>0.0.2-SNAPSHOT</version> - <properties> - <logback.version>1.4.6</logback.version> - <lombok.version>1.18.26</lombok.version> - <slf4j.version>2.0.5</slf4j.version> - <java.source.version>17</java.source.version> - <java.target.version>17</java.target.version> - </properties> + <properties> + <logback.version>1.4.6</logback.version> + <lombok.version>1.18.26</lombok.version> + <slf4j.version>2.0.5</slf4j.version> + <java.source.version>17</java.source.version> + <java.target.version>17</java.target.version> + </properties> - <dependencies> - <dependency> - <groupId>ch.fritteli.labyrinth</groupId> - <artifactId>labyrinth-generator</artifactId> - <version>0.0.2</version> - </dependency> - <dependency> - <groupId>io.vavr</groupId> - <artifactId>vavr</artifactId> - </dependency> - <dependency> - <groupId>org.projectlombok</groupId> - <artifactId>lombok</artifactId> - </dependency> - <dependency> - <groupId>org.jetbrains</groupId> - <artifactId>annotations</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-api</artifactId> - <version>${slf4j.version}</version> - </dependency> - <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - <version>${logback.version}</version> - </dependency> - <dependency> - <groupId>io.undertow</groupId> - <artifactId>undertow-core</artifactId> - <version>2.2.22.Final</version> - </dependency> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>ch.fritteli.labyrinth</groupId> + <artifactId>labyrinth-generator</artifactId> + <version>0.0.2</version> + </dependency> + <dependency> + <groupId>io.vavr</groupId> + <artifactId>vavr</artifactId> + </dependency> + <dependency> + <groupId>org.projectlombok</groupId> + <artifactId>lombok</artifactId> + </dependency> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>${logback.version}</version> + </dependency> + <dependency> + <groupId>io.undertow</groupId> + <artifactId>undertow-core</artifactId> + <version>2.2.22.Final</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + </dependency> + </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>3.2.4</version> - <configuration> - <transformers> - <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <mainClass>ch.fritteli.labyrinth.server.Main</mainClass> - </transformer> - </transformers> - </configuration> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - <scm> - <connection>scm:git:git://gittr.ch/java/labyrinth-server.git</connection> - <developerConnection>scm:git:ssh://git@gittr.ch/java/labyrinth-server.git</developerConnection> - <url>https://gittr.ch/java/labyrinth-server</url> - <tag>HEAD</tag> - </scm> - <distributionManagement> - <repository> - <id>repo.gittr.ch</id> - <name>gittr.ch</name> - <url>https://repo.gittr.ch/releases/</url> - </repository> - <snapshotRepository> - <id>repo.gittr.ch</id> - <name>gittr.ch</name> - <url>https://repo.gittr.ch/snapshots/</url> - </snapshotRepository> - </distributionManagement> - <repositories> - <repository> - <id>repo.gittr.ch.releases</id> - <url>https://repo.gittr.ch/releases/</url> - <releases> - <enabled>true</enabled> - <updatePolicy>never</updatePolicy> - </releases> - <snapshots> - <enabled>false</enabled> - <updatePolicy>never</updatePolicy> - </snapshots> - </repository> - <repository> - <id>repo.gittr.ch.snapshots</id> - <url>https://repo.gittr.ch/snapshots/</url> - <releases> - <enabled>false</enabled> - <updatePolicy>never</updatePolicy> - </releases> - <snapshots> - <enabled>true</enabled> - <updatePolicy>always</updatePolicy> - </snapshots> - </repository> - </repositories> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.2.4</version> + <configuration> + <transformers> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <mainClass>ch.fritteli.labyrinth.server.Main</mainClass> + </transformer> + </transformers> + </configuration> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <scm> + <connection>scm:git:git://gittr.ch/java/labyrinth-server.git</connection> + <developerConnection>scm:git:ssh://git@gittr.ch/java/labyrinth-server.git</developerConnection> + <url>https://gittr.ch/java/labyrinth-server</url> + <tag>HEAD</tag> + </scm> + <distributionManagement> + <repository> + <id>repo.gittr.ch</id> + <name>gittr.ch</name> + <url>https://repo.gittr.ch/releases/</url> + </repository> + <snapshotRepository> + <id>repo.gittr.ch</id> + <name>gittr.ch</name> + <url>https://repo.gittr.ch/snapshots/</url> + </snapshotRepository> + </distributionManagement> + <repositories> + <repository> + <id>repo.gittr.ch.releases</id> + <url>https://repo.gittr.ch/releases/</url> + <releases> + <enabled>true</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>false</enabled> + <updatePolicy>never</updatePolicy> + </snapshots> + </repository> + <repository> + <id>repo.gittr.ch.snapshots</id> + <url>https://repo.gittr.ch/snapshots/</url> + <releases> + <enabled>false</enabled> + <updatePolicy>never</updatePolicy> + </releases> + <snapshots> + <enabled>true</enabled> + <updatePolicy>always</updatePolicy> + </snapshots> + </repository> + </repositories> </project> diff --git a/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java b/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java index aab20f6..f082742 100644 --- a/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java +++ b/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java @@ -119,15 +119,13 @@ public class LabyrinthServer { } 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() - ) - ); + 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(); @@ -254,7 +252,7 @@ public class LabyrinthServer { } } - private enum OutputType { + public enum OutputType { TEXT_PLAIN("text/plain; charset=UTF-8", labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), "txt", @@ -303,7 +301,7 @@ public class LabyrinthServer { this.names = List.of(names); } - static Option<OutputType> ofString(@Nullable final String name) { + public static Option<OutputType> ofString(@Nullable final String name) { if (name == null) { return Option.none(); } @@ -316,7 +314,7 @@ public class LabyrinthServer { return this.names.last(); } - byte[] render(@NonNull final Labyrinth labyrinth) { + public byte[] render(@NonNull final Labyrinth labyrinth) { return this.render.apply(labyrinth); } } diff --git a/src/main/java/ch/fritteli/labyrinth/server/ServerConfig.java b/src/main/java/ch/fritteli/labyrinth/server/ServerConfig.java index 58cee13..fc161dd 100644 --- a/src/main/java/ch/fritteli/labyrinth/server/ServerConfig.java +++ b/src/main/java/ch/fritteli/labyrinth/server/ServerConfig.java @@ -10,7 +10,6 @@ import org.jetbrains.annotations.Nullable; import java.net.InetAddress; - @AllArgsConstructor(access = AccessLevel.PRIVATE) @Slf4j @Value @@ -18,8 +17,7 @@ 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 { @@ -28,6 +26,19 @@ 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); @@ -36,26 +47,16 @@ 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: " + address, cause)); - } - 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, 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; + .map(ServerConfig::validatePort) + .getOrElseThrow(cause -> new ConfigurationException( + "Failed to parse port specified in system property '" + SYSPROP_PORT + "': " + portString, + cause + )); } } diff --git a/src/main/java/ch/fritteli/labyrinth/server/StaticResourcesFileHandler.java b/src/main/java/ch/fritteli/labyrinth/server/StaticResourcesFileHandler.java index d1cabfc..e6911e8 100644 --- a/src/main/java/ch/fritteli/labyrinth/server/StaticResourcesFileHandler.java +++ b/src/main/java/ch/fritteli/labyrinth/server/StaticResourcesFileHandler.java @@ -24,43 +24,6 @@ public class StaticResourcesFileHandler implements HttpHandler { log.debug("Created {}", this.getClass().getSimpleName()); } - private static void redirect(@NonNull final HttpExchange exchange, @NonNull final String target) throws IOException { - log.debug("Sending redirect to {}", target); - exchange.getResponseHeaders().add("Location", target); - exchange.sendResponseHeaders(302, -1); - } - - private static void notFound(@NonNull final HttpExchange exchange, @NonNull final String path) throws IOException { - log.debug("Resource '{}' not found, replying with HTTP 404", path); - exchange.getResponseHeaders().add("Content-type", "text/plain; charset=utf-8"); - exchange.sendResponseHeaders(404, 0); - exchange.getResponseBody().write("404 - Not found".getBytes(StandardCharsets.UTF_8)); - exchange.getResponseBody().flush(); - } - - @NonNull - private static byte[] getBytes(@NonNull final String path) throws IOException { - final InputStream stream = StaticResourcesFileHandler.class.getClassLoader().getResourceAsStream(WEBASSETS_DIRECTORY + path); - if (stream == null) { - log.debug("Resource '{}' not found in classpath.", path); - return new byte[0]; - } - final byte[] response = IOUtils.toByteArray(stream); - log.debug("Sending reply; {} bytes", response.length); - return response; - } - - @Nullable - private static String getMimeType(@NonNull final String path) { - if (path.endsWith(".html")) { - return "text/html"; - } - if (path.endsWith(".css")) { - return "text/css"; - } - return null; - } - @Override public void handle(@NonNull final HttpExchange exchange) throws IOException { this.executorService.submit(() -> { @@ -86,7 +49,13 @@ public class StaticResourcesFileHandler implements HttpHandler { notFound(exchange, path); return; } - log.debug("Serving {}{} with mimetype {}: {} bytes", WEBASSETS_DIRECTORY, path, mimeType, responseBytes.length); + log.debug( + "Serving {}{} with mimetype {}: {} bytes", + WEBASSETS_DIRECTORY, + path, + mimeType, + responseBytes.length + ); exchange.getResponseHeaders().add("Content-type", mimeType); exchange.sendResponseHeaders(200, 0); exchange.getResponseBody().write(responseBytes); @@ -98,4 +67,43 @@ public class StaticResourcesFileHandler implements HttpHandler { } }); } + + private static void redirect(@NonNull final HttpExchange exchange, @NonNull final String target) throws + IOException { + log.debug("Sending redirect to {}", target); + exchange.getResponseHeaders().add("Location", target); + exchange.sendResponseHeaders(302, -1); + } + + private static void notFound(@NonNull final HttpExchange exchange, @NonNull final String path) throws IOException { + log.debug("Resource '{}' not found, replying with HTTP 404", path); + exchange.getResponseHeaders().add("Content-type", "text/plain; charset=utf-8"); + exchange.sendResponseHeaders(404, 0); + exchange.getResponseBody().write("404 - Not found".getBytes(StandardCharsets.UTF_8)); + exchange.getResponseBody().flush(); + } + + @Nullable + private static String getMimeType(@NonNull final String path) { + if (path.endsWith(".html")) { + return "text/html"; + } + if (path.endsWith(".css")) { + return "text/css"; + } + return null; + } + + @NonNull + private static byte[] getBytes(@NonNull final String path) throws IOException { + final InputStream stream = StaticResourcesFileHandler.class.getClassLoader() + .getResourceAsStream(WEBASSETS_DIRECTORY + path); + if (stream == null) { + log.debug("Resource '{}' not found in classpath.", path); + return new byte[0]; + } + final byte[] response = IOUtils.toByteArray(stream); + log.debug("Sending reply; {} bytes", response.length); + return response; + } } diff --git a/src/main/java/ch/fritteli/labyrinth/server/undertow_playground/UndertowPlayground.java b/src/main/java/ch/fritteli/labyrinth/server/undertow_playground/UndertowPlayground.java index b64a343..8bb037f 100644 --- a/src/main/java/ch/fritteli/labyrinth/server/undertow_playground/UndertowPlayground.java +++ b/src/main/java/ch/fritteli/labyrinth/server/undertow_playground/UndertowPlayground.java @@ -1,5 +1,7 @@ package ch.fritteli.labyrinth.server.undertow_playground; +import ch.fritteli.labyrinth.generator.model.Labyrinth; +import ch.fritteli.labyrinth.server.LabyrinthServer; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.RoutingHandler; @@ -10,69 +12,69 @@ import io.vavr.control.Option; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import java.nio.ByteBuffer; import java.util.Deque; import java.util.Map; +import java.util.Random; @Slf4j public class UndertowPlayground { - public static final RoutingHandler r = new RoutingHandler() - .get("/create/{output}", new HttpHandler() { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - if (exchange.isInIoThread()) { - exchange.dispatch(this); - return; - } - final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); - final Option<String> output = getFirstOption(queryParameters, "output"); - final Option<Integer> width = getIntOption(queryParameters, "width"); - final Option<Integer> height = getIntOption(queryParameters, "height"); - final Option<Integer> id = getIntOption(queryParameters, "id"); + public static final RoutingHandler r = new RoutingHandler().get("/create/{output}", new HttpHandler() { + @Override + public void handleRequest(HttpServerExchange exchange) throws Exception { + if (exchange.isInIoThread()) { + exchange.dispatch(this); + return; + } + final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); + final Option<String> output = getFirstOption(queryParameters, "output"); + final Option<Integer> width = getIntOption(queryParameters, "width"); + final Option<Integer> height = getIntOption(queryParameters, "height"); + final Option<Integer> id = getIntOption(queryParameters, "id"); - log.info("Output: {}", output); - log.info("Width: {}", width); - log.info("Height: {}", height); - log.info("Id: {}", id); - exchange.getResponseSender().send( - "Output: " + output + - ", Width: " + width + - ", Height: " + height + - ", Id: " + id - ); - } - }) - .post("/render", new HttpHandler() { - @Override - public void handleRequest(final HttpServerExchange exchange) { - if (exchange.isInIoThread()) { - exchange.dispatch(this); - return; - } - exchange.getResponseSender().send("TODO: read body, render stuff"); - } - }) - .setFallbackHandler(new HttpHandler() { - @Override - public void handleRequest(HttpServerExchange exchange) throws Exception { - exchange.getResponseSender().send("Request: " + exchange.getRequestURI()); - final HeaderValues strings = exchange.getRequestHeaders().get(Headers.ACCEPT); - strings.peekFirst(); - } - } - ); + log.info("Output: {}", output); + log.info("Width: {}", width); + log.info("Height: {}", height); + log.info("Id: {}", id); + final Integer theId = id.getOrElse(() -> new Random().nextInt()); + final Labyrinth labyrinth = new Labyrinth(width.get(), height.get(), theId); + final LabyrinthServer.OutputType outputType = output.flatMap(LabyrinthServer.OutputType::ofString).get(); + final byte[] result = outputType.render(labyrinth); + exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, outputType.getContentType()); + exchange.getResponseHeaders().put(HttpString.tryFromString("X-Labyrinth-ID"), String.valueOf(theId)); + exchange.getResponseHeaders() + .put(HttpString.tryFromString("X-Labyrinth-Width"), String.valueOf(width.get())); + exchange.getResponseHeaders() + .put(HttpString.tryFromString("X-Labyrinth-Height"), String.valueOf(height.get())); + exchange.getResponseSender().send(ByteBuffer.wrap(result)); + } + }).post("/render", new HttpHandler() { + @Override + public void handleRequest(final HttpServerExchange exchange) { + if (exchange.isInIoThread()) { + exchange.dispatch(this); + return; + } + exchange.getResponseSender().send("TODO: read body, render stuff"); + } + }).setFallbackHandler(new HttpHandler() { + @Override + public void handleRequest(HttpServerExchange exchange) throws Exception { + exchange.getResponseSender().send("Request: " + exchange.getRequestURI()); + final HeaderValues strings = exchange.getRequestHeaders().get(Headers.ACCEPT); + strings.peekFirst(); + } + }); @NonNull - private static Option<String> getFirstOption(@NonNull final Map<String, Deque<String>> queryParams, @NonNull final String paramName) { - return Option.of(queryParams.get(paramName)) - .map(Deque::peek) - .flatMap(Option::of); + private static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, + @NonNull final String paramName) { + return getFirstOption(queryParams, paramName).toTry().map(Integer::parseInt).toOption(); } @NonNull - private static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, @NonNull final String paramName) { - return getFirstOption(queryParams, paramName) - .toTry() - .map(Integer::parseInt) - .toOption(); + private static Option<String> getFirstOption(@NonNull final Map<String, Deque<String>> queryParams, + @NonNull final String paramName) { + return Option.of(queryParams.get(paramName)).map(Deque::peek).flatMap(Option::of); } } diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 4bba3c1..f484fc8 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,17 +1,17 @@ <?xml version="1.0" encoding="utf-8" ?> <configuration> - <shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/> + <shutdownHook class="ch.qos.logback.core.hook.DefaultShutdownHook"/> - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <!-- 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> - </encoder> - </appender> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <!-- 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> + </encoder> + </appender> - <root level="info"> - <appender-ref ref="STDOUT"/> - </root> - <logger name="ch.fritteli.labyrinth.server.StaticResourcesFileHandler" level="debug"/> + <root level="info"> + <appender-ref ref="STDOUT"/> + </root> + <logger name="ch.fritteli.labyrinth.server.StaticResourcesFileHandler" level="debug"/> </configuration> diff --git a/src/main/resources/webassets/index.html b/src/main/resources/webassets/index.html index 3444b42..b97b934 100644 --- a/src/main/resources/webassets/index.html +++ b/src/main/resources/webassets/index.html @@ -3,7 +3,7 @@ <head> <meta charset="UTF-8"> <title>Labyrinth Generator</title> - <link rel="stylesheet" href="style.css"> + <link href="style.css" rel="stylesheet"> </head> <body> <div class="content"> @@ -11,8 +11,8 @@ <p>Enter some values, click the "Create!" button and see what happens!</p> <form action="/create" method="get"> <div class="inputs-wrapper"> - <label for="width">Width:</label><input id="width" name="width" type="number" min="1" required> - <label for="height">Height:</label><input id="height" name="height" type="number" min="1" required> + <label for="width">Width:</label><input id="width" min="1" name="width" required type="number"> + <label for="height">Height:</label><input id="height" min="1" name="height" required type="number"> <label for="output">Output format:</label> <select id="output" name="output" required> <option label="HTML Document" value="html"></option> @@ -24,7 +24,7 @@ <label for="id">Seed (optional):</label><input id="id" name="id" type="number"> </div> <div class="controls-wrapper"> - <button type="submit" class="primary">Create!</button> + <button class="primary" type="submit">Create!</button> <button type="reset">Reset form</button> </div> </form>