Reformat everything.
First prototype of runnign with untertow.
This commit is contained in:
		
							parent
							
								
									682e0d0f25
								
							
						
					
					
						commit
						0bc1114aec
					
				
					 8 changed files with 281 additions and 270 deletions
				
			
		|  | @ -1,12 +1,12 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?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" | <settings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
| 		  xmlns="http://maven.apache.org/SETTINGS/1.1.0" |           xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" | ||||||
| 		  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |           xmlns="http://maven.apache.org/SETTINGS/1.1.0"> | ||||||
| 	<servers> |     <servers> | ||||||
| 		<server> |         <server> | ||||||
| 			<id>repo.gittr.ch</id> |             <id>repo.gittr.ch</id> | ||||||
| 			<username>ci</username> |             <username>ci</username> | ||||||
| 			<password>${env.REPO_TOKEN}</password> |             <password>${env.REPO_TOKEN}</password> | ||||||
| 		</server> |         </server> | ||||||
| 	</servers> |     </servers> | ||||||
| </settings> | </settings> | ||||||
|  |  | ||||||
							
								
								
									
										248
									
								
								pom.xml
									
										
									
									
									
								
							
							
						
						
									
										248
									
								
								pom.xml
									
										
									
									
									
								
							|  | @ -1,130 +1,132 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?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"> | <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
| 	<modelVersion>4.0.0</modelVersion> |          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> |     <parent> | ||||||
| 		<groupId>ch.fritteli</groupId> |         <groupId>ch.fritteli</groupId> | ||||||
| 		<artifactId>fritteli-build-parent</artifactId> |         <artifactId>fritteli-build-parent</artifactId> | ||||||
| 		<version>2.0.4</version> |         <version>2.0.4</version> | ||||||
| 	</parent> |     </parent> | ||||||
| 
 | 
 | ||||||
| 	<groupId>ch.fritteli.labyrinth</groupId> |     <groupId>ch.fritteli.labyrinth</groupId> | ||||||
| 	<artifactId>labyrinth-server</artifactId> |     <artifactId>labyrinth-server</artifactId> | ||||||
| 	<version>0.0.2-SNAPSHOT</version> |     <version>0.0.2-SNAPSHOT</version> | ||||||
| 
 | 
 | ||||||
| 	<properties> |     <properties> | ||||||
| 		<logback.version>1.4.6</logback.version> |         <logback.version>1.4.6</logback.version> | ||||||
| 		<lombok.version>1.18.26</lombok.version> |         <lombok.version>1.18.26</lombok.version> | ||||||
| 		<slf4j.version>2.0.5</slf4j.version> |         <slf4j.version>2.0.5</slf4j.version> | ||||||
| 		<java.source.version>17</java.source.version> |         <java.source.version>17</java.source.version> | ||||||
| 		<java.target.version>17</java.target.version> |         <java.target.version>17</java.target.version> | ||||||
| 	</properties> |     </properties> | ||||||
| 
 | 
 | ||||||
| 	<dependencies> |     <dependencies> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>ch.fritteli.labyrinth</groupId> |             <groupId>ch.fritteli.labyrinth</groupId> | ||||||
| 			<artifactId>labyrinth-generator</artifactId> |             <artifactId>labyrinth-generator</artifactId> | ||||||
| 			<version>0.0.2</version> |             <version>0.0.2</version> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>io.vavr</groupId> |             <groupId>io.vavr</groupId> | ||||||
| 			<artifactId>vavr</artifactId> |             <artifactId>vavr</artifactId> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>org.projectlombok</groupId> |             <groupId>org.projectlombok</groupId> | ||||||
| 			<artifactId>lombok</artifactId> |             <artifactId>lombok</artifactId> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>org.jetbrains</groupId> |             <groupId>org.jetbrains</groupId> | ||||||
| 			<artifactId>annotations</artifactId> |             <artifactId>annotations</artifactId> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>org.slf4j</groupId> |             <groupId>org.slf4j</groupId> | ||||||
| 			<artifactId>slf4j-api</artifactId> |             <artifactId>slf4j-api</artifactId> | ||||||
| 			<version>${slf4j.version}</version> |             <version>${slf4j.version}</version> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>ch.qos.logback</groupId> |             <groupId>ch.qos.logback</groupId> | ||||||
| 			<artifactId>logback-classic</artifactId> |             <artifactId>logback-classic</artifactId> | ||||||
| 			<version>${logback.version}</version> |             <version>${logback.version}</version> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>io.undertow</groupId> |             <groupId>io.undertow</groupId> | ||||||
| 			<artifactId>undertow-core</artifactId> |             <artifactId>undertow-core</artifactId> | ||||||
| 			<version>2.2.22.Final</version> |             <version>2.2.22.Final</version> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 		<dependency> |         <dependency> | ||||||
| 			<groupId>org.junit.jupiter</groupId> |             <groupId>org.junit.jupiter</groupId> | ||||||
| 			<artifactId>junit-jupiter-api</artifactId> |             <artifactId>junit-jupiter-api</artifactId> | ||||||
| 		</dependency> |         </dependency> | ||||||
| 	</dependencies> |     </dependencies> | ||||||
| 
 | 
 | ||||||
| 	<build> |     <build> | ||||||
| 		<plugins> |         <plugins> | ||||||
| 			<plugin> |             <plugin> | ||||||
| 				<groupId>org.apache.maven.plugins</groupId> |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
| 				<artifactId>maven-shade-plugin</artifactId> |                 <artifactId>maven-shade-plugin</artifactId> | ||||||
| 				<version>3.2.4</version> |                 <version>3.2.4</version> | ||||||
| 				<configuration> |                 <configuration> | ||||||
| 					<transformers> |                     <transformers> | ||||||
| 						<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> |                         <transformer | ||||||
| 							<mainClass>ch.fritteli.labyrinth.server.Main</mainClass> |                                 implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> | ||||||
| 						</transformer> |                             <mainClass>ch.fritteli.labyrinth.server.Main</mainClass> | ||||||
| 					</transformers> |                         </transformer> | ||||||
| 				</configuration> |                     </transformers> | ||||||
| 				<executions> |                 </configuration> | ||||||
| 					<execution> |                 <executions> | ||||||
| 						<phase>package</phase> |                     <execution> | ||||||
| 						<goals> |                         <phase>package</phase> | ||||||
| 							<goal>shade</goal> |                         <goals> | ||||||
| 						</goals> |                             <goal>shade</goal> | ||||||
| 					</execution> |                         </goals> | ||||||
| 				</executions> |                     </execution> | ||||||
| 			</plugin> |                 </executions> | ||||||
| 		</plugins> |             </plugin> | ||||||
| 	</build> |         </plugins> | ||||||
| 	<scm> |     </build> | ||||||
| 		<connection>scm:git:git://gittr.ch/java/labyrinth-server.git</connection> |     <scm> | ||||||
| 		<developerConnection>scm:git:ssh://git@gittr.ch/java/labyrinth-server.git</developerConnection> |         <connection>scm:git:git://gittr.ch/java/labyrinth-server.git</connection> | ||||||
| 		<url>https://gittr.ch/java/labyrinth-server</url> |         <developerConnection>scm:git:ssh://git@gittr.ch/java/labyrinth-server.git</developerConnection> | ||||||
| 		<tag>HEAD</tag> |         <url>https://gittr.ch/java/labyrinth-server</url> | ||||||
| 	</scm> |         <tag>HEAD</tag> | ||||||
| 	<distributionManagement> |     </scm> | ||||||
| 		<repository> |     <distributionManagement> | ||||||
| 			<id>repo.gittr.ch</id> |         <repository> | ||||||
| 			<name>gittr.ch</name> |             <id>repo.gittr.ch</id> | ||||||
| 			<url>https://repo.gittr.ch/releases/</url> |             <name>gittr.ch</name> | ||||||
| 		</repository> |             <url>https://repo.gittr.ch/releases/</url> | ||||||
| 		<snapshotRepository> |         </repository> | ||||||
| 			<id>repo.gittr.ch</id> |         <snapshotRepository> | ||||||
| 			<name>gittr.ch</name> |             <id>repo.gittr.ch</id> | ||||||
| 			<url>https://repo.gittr.ch/snapshots/</url> |             <name>gittr.ch</name> | ||||||
| 		</snapshotRepository> |             <url>https://repo.gittr.ch/snapshots/</url> | ||||||
| 	</distributionManagement> |         </snapshotRepository> | ||||||
| 	<repositories> |     </distributionManagement> | ||||||
| 		<repository> |     <repositories> | ||||||
| 			<id>repo.gittr.ch.releases</id> |         <repository> | ||||||
| 			<url>https://repo.gittr.ch/releases/</url> |             <id>repo.gittr.ch.releases</id> | ||||||
| 			<releases> |             <url>https://repo.gittr.ch/releases/</url> | ||||||
| 				<enabled>true</enabled> |             <releases> | ||||||
| 				<updatePolicy>never</updatePolicy> |                 <enabled>true</enabled> | ||||||
| 			</releases> |                 <updatePolicy>never</updatePolicy> | ||||||
| 			<snapshots> |             </releases> | ||||||
| 				<enabled>false</enabled> |             <snapshots> | ||||||
| 				<updatePolicy>never</updatePolicy> |                 <enabled>false</enabled> | ||||||
| 			</snapshots> |                 <updatePolicy>never</updatePolicy> | ||||||
| 		</repository> |             </snapshots> | ||||||
| 		<repository> |         </repository> | ||||||
| 			<id>repo.gittr.ch.snapshots</id> |         <repository> | ||||||
| 			<url>https://repo.gittr.ch/snapshots/</url> |             <id>repo.gittr.ch.snapshots</id> | ||||||
| 			<releases> |             <url>https://repo.gittr.ch/snapshots/</url> | ||||||
| 				<enabled>false</enabled> |             <releases> | ||||||
| 				<updatePolicy>never</updatePolicy> |                 <enabled>false</enabled> | ||||||
| 			</releases> |                 <updatePolicy>never</updatePolicy> | ||||||
| 			<snapshots> |             </releases> | ||||||
| 				<enabled>true</enabled> |             <snapshots> | ||||||
| 				<updatePolicy>always</updatePolicy> |                 <enabled>true</enabled> | ||||||
| 			</snapshots> |                 <updatePolicy>always</updatePolicy> | ||||||
| 		</repository> |             </snapshots> | ||||||
| 	</repositories> |         </repository> | ||||||
|  |     </repositories> | ||||||
| </project> | </project> | ||||||
|  |  | ||||||
|  | @ -119,15 +119,13 @@ public class LabyrinthServer { | ||||||
|                 } |                 } | ||||||
|                 responseHeaders.add("Content-type", output.getContentType()); |                 responseHeaders.add("Content-type", output.getContentType()); | ||||||
|                 if (output.isAttachment()) { |                 if (output.isAttachment()) { | ||||||
|                     responseHeaders.add( |                     responseHeaders.add("Content-disposition", String.format( | ||||||
|                             "Content-disposition", |                             "attachment; filename=\"labyrinth-%dx%d-%d.%s\"", | ||||||
|                             String.format("attachment; filename=\"labyrinth-%dx%d-%d.%s\"", |                             width, | ||||||
|                                           width, |                             height, | ||||||
|                                           height, |                             id, | ||||||
|                                           id, |                             output.getFileExtension() | ||||||
|                                           output.getFileExtension() |                     )); | ||||||
|                             ) |  | ||||||
|                     ); |  | ||||||
|                 } |                 } | ||||||
|                 exchange.sendResponseHeaders(200, 0); |                 exchange.sendResponseHeaders(200, 0); | ||||||
|                 final OutputStream responseBody = exchange.getResponseBody(); |                 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", |         TEXT_PLAIN("text/plain; charset=UTF-8", | ||||||
|                    labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), |                    labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), | ||||||
|                    "txt", |                    "txt", | ||||||
|  | @ -303,7 +301,7 @@ public class LabyrinthServer { | ||||||
|             this.names = List.of(names); |             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) { |             if (name == null) { | ||||||
|                 return Option.none(); |                 return Option.none(); | ||||||
|             } |             } | ||||||
|  | @ -316,7 +314,7 @@ public class LabyrinthServer { | ||||||
|             return this.names.last(); |             return this.names.last(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         byte[] render(@NonNull final Labyrinth labyrinth) { |         public byte[] render(@NonNull final Labyrinth labyrinth) { | ||||||
|             return this.render.apply(labyrinth); |             return this.render.apply(labyrinth); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ import org.jetbrains.annotations.Nullable; | ||||||
| 
 | 
 | ||||||
| import java.net.InetAddress; | import java.net.InetAddress; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| @AllArgsConstructor(access = AccessLevel.PRIVATE) | @AllArgsConstructor(access = AccessLevel.PRIVATE) | ||||||
| @Slf4j | @Slf4j | ||||||
| @Value | @Value | ||||||
|  | @ -18,8 +17,7 @@ public class ServerConfig { | ||||||
|     public static final String SYSPROP_HOST = "fritteli.labyrinth.server.host"; |     public static final String SYSPROP_HOST = "fritteli.labyrinth.server.host"; | ||||||
|     public static final String SYSPROP_PORT = "fritteli.labyrinth.server.port"; |     public static final String SYSPROP_PORT = "fritteli.labyrinth.server.port"; | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull InetAddress address; | ||||||
|     InetAddress address; |  | ||||||
|     int port; |     int port; | ||||||
| 
 | 
 | ||||||
|     public ServerConfig(@Nullable final String address, final int port) throws ConfigurationException { |     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); |         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 |     @NonNull | ||||||
|     public static ServerConfig init() throws ConfigurationException { |     public static ServerConfig init() throws ConfigurationException { | ||||||
|         final String host = System.getProperty(SYSPROP_HOST); |         final String host = System.getProperty(SYSPROP_HOST); | ||||||
|  | @ -36,26 +47,16 @@ public class ServerConfig { | ||||||
|         return new ServerConfig(host, port); |         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) { |     private static int validatePort(@Nullable final String portString) { | ||||||
|         if (portString == null) { |         if (portString == null) { | ||||||
|             log.info("No port configured; using default."); |             log.info("No port configured; using default."); | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|         return Try.of(() -> Integer.valueOf(portString)) |         return Try.of(() -> Integer.valueOf(portString)) | ||||||
|                 .map(ServerConfig::validatePort) |                   .map(ServerConfig::validatePort) | ||||||
|                 .getOrElseThrow(cause -> new ConfigurationException("Failed to parse port specified in system property '" + SYSPROP_PORT + "': " + portString, cause)); |                   .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; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -24,43 +24,6 @@ public class StaticResourcesFileHandler implements HttpHandler { | ||||||
|         log.debug("Created {}", this.getClass().getSimpleName()); |         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 |     @Override | ||||||
|     public void handle(@NonNull final HttpExchange exchange) throws IOException { |     public void handle(@NonNull final HttpExchange exchange) throws IOException { | ||||||
|         this.executorService.submit(() -> { |         this.executorService.submit(() -> { | ||||||
|  | @ -86,7 +49,13 @@ public class StaticResourcesFileHandler implements HttpHandler { | ||||||
|                     notFound(exchange, path); |                     notFound(exchange, path); | ||||||
|                     return; |                     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.getResponseHeaders().add("Content-type", mimeType); | ||||||
|                 exchange.sendResponseHeaders(200, 0); |                 exchange.sendResponseHeaders(200, 0); | ||||||
|                 exchange.getResponseBody().write(responseBytes); |                 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; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| package ch.fritteli.labyrinth.server.undertow_playground; | 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.HttpHandler; | ||||||
| import io.undertow.server.HttpServerExchange; | import io.undertow.server.HttpServerExchange; | ||||||
| import io.undertow.server.RoutingHandler; | import io.undertow.server.RoutingHandler; | ||||||
|  | @ -10,69 +12,69 @@ import io.vavr.control.Option; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| 
 | 
 | ||||||
|  | import java.nio.ByteBuffer; | ||||||
| import java.util.Deque; | import java.util.Deque; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  | import java.util.Random; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class UndertowPlayground { | public class UndertowPlayground { | ||||||
|     public static final RoutingHandler r = new RoutingHandler() |     public static final RoutingHandler r = new RoutingHandler().get("/create/{output}", new HttpHandler() { | ||||||
|             .get("/create/{output}", new HttpHandler() { |         @Override | ||||||
|                 @Override |         public void handleRequest(HttpServerExchange exchange) throws Exception { | ||||||
|                 public void handleRequest(HttpServerExchange exchange) throws Exception { |             if (exchange.isInIoThread()) { | ||||||
|                     if (exchange.isInIoThread()) { |                 exchange.dispatch(this); | ||||||
|                         exchange.dispatch(this); |                 return; | ||||||
|                         return; |             } | ||||||
|                     } |             final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); | ||||||
|                     final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); |             final Option<String> output = getFirstOption(queryParameters, "output"); | ||||||
|                     final Option<String> output = getFirstOption(queryParameters, "output"); |             final Option<Integer> width = getIntOption(queryParameters, "width"); | ||||||
|                     final Option<Integer> width = getIntOption(queryParameters, "width"); |             final Option<Integer> height = getIntOption(queryParameters, "height"); | ||||||
|                     final Option<Integer> height = getIntOption(queryParameters, "height"); |             final Option<Integer> id = getIntOption(queryParameters, "id"); | ||||||
|                     final Option<Integer> id = getIntOption(queryParameters, "id"); |  | ||||||
| 
 | 
 | ||||||
|                     log.info("Output: {}", output); |             log.info("Output: {}", output); | ||||||
|                     log.info("Width:  {}", width); |             log.info("Width:  {}", width); | ||||||
|                     log.info("Height: {}", height); |             log.info("Height: {}", height); | ||||||
|                     log.info("Id:     {}", id); |             log.info("Id:     {}", id); | ||||||
|                     exchange.getResponseSender().send( |             final Integer theId = id.getOrElse(() -> new Random().nextInt()); | ||||||
|                             "Output: " + output + |             final Labyrinth labyrinth = new Labyrinth(width.get(), height.get(), theId); | ||||||
|                                     ", Width: " + width + |             final LabyrinthServer.OutputType outputType = output.flatMap(LabyrinthServer.OutputType::ofString).get(); | ||||||
|                                     ", Height: " + height + |             final byte[] result = outputType.render(labyrinth); | ||||||
|                                     ", Id: " + id |             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())); | ||||||
|             .post("/render", new HttpHandler() { |             exchange.getResponseHeaders() | ||||||
|                 @Override |                     .put(HttpString.tryFromString("X-Labyrinth-Height"), String.valueOf(height.get())); | ||||||
|                 public void handleRequest(final HttpServerExchange exchange) { |             exchange.getResponseSender().send(ByteBuffer.wrap(result)); | ||||||
|                     if (exchange.isInIoThread()) { |         } | ||||||
|                         exchange.dispatch(this); |     }).post("/render", new HttpHandler() { | ||||||
|                         return; |         @Override | ||||||
|                     } |         public void handleRequest(final HttpServerExchange exchange) { | ||||||
|                     exchange.getResponseSender().send("TODO: read body, render stuff"); |             if (exchange.isInIoThread()) { | ||||||
|                 } |                 exchange.dispatch(this); | ||||||
|             }) |                 return; | ||||||
|             .setFallbackHandler(new HttpHandler() { |             } | ||||||
|                                     @Override |             exchange.getResponseSender().send("TODO: read body, render stuff"); | ||||||
|                                     public void handleRequest(HttpServerExchange exchange) throws Exception { |         } | ||||||
|                                         exchange.getResponseSender().send("Request: " + exchange.getRequestURI()); |     }).setFallbackHandler(new HttpHandler() { | ||||||
|                                         final HeaderValues strings = exchange.getRequestHeaders().get(Headers.ACCEPT); |         @Override | ||||||
|                                         strings.peekFirst(); |         public void handleRequest(HttpServerExchange exchange) throws Exception { | ||||||
|                                     } |             exchange.getResponseSender().send("Request: " + exchange.getRequestURI()); | ||||||
|                                 } |             final HeaderValues strings = exchange.getRequestHeaders().get(Headers.ACCEPT); | ||||||
|             ); |             strings.peekFirst(); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|     private static Option<String> getFirstOption(@NonNull final Map<String, Deque<String>> queryParams, @NonNull final String paramName) { |     private static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, | ||||||
|         return Option.of(queryParams.get(paramName)) |                                                 @NonNull final String paramName) { | ||||||
|                 .map(Deque::peek) |         return getFirstOption(queryParams, paramName).toTry().map(Integer::parseInt).toOption(); | ||||||
|                 .flatMap(Option::of); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|     private static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, @NonNull final String paramName) { |     private static Option<String> getFirstOption(@NonNull final Map<String, Deque<String>> queryParams, | ||||||
|         return getFirstOption(queryParams, paramName) |                                                  @NonNull final String paramName) { | ||||||
|                 .toTry() |         return Option.of(queryParams.get(paramName)).map(Deque::peek).flatMap(Option::of); | ||||||
|                 .map(Integer::parseInt) |  | ||||||
|                 .toOption(); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,17 +1,17 @@ | ||||||
| <?xml version="1.0" encoding="utf-8" ?> | <?xml version="1.0" encoding="utf-8" ?> | ||||||
| <configuration> | <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"> |     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | ||||||
| 		<!-- encoders are by default assigned the type |         <!-- encoders are by default assigned the type | ||||||
| 		ch.qos.logback.classic.encoder.PatternLayoutEncoder --> |         ch.qos.logback.classic.encoder.PatternLayoutEncoder --> | ||||||
| 		<encoder> |         <encoder> | ||||||
| 			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> |             <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> | ||||||
| 		</encoder> |         </encoder> | ||||||
| 	</appender> |     </appender> | ||||||
| 
 | 
 | ||||||
| 	<root level="info"> |     <root level="info"> | ||||||
| 		<appender-ref ref="STDOUT"/> |         <appender-ref ref="STDOUT"/> | ||||||
| 	</root> |     </root> | ||||||
| 	<logger name="ch.fritteli.labyrinth.server.StaticResourcesFileHandler" level="debug"/> |     <logger name="ch.fritteli.labyrinth.server.StaticResourcesFileHandler" level="debug"/> | ||||||
| </configuration> | </configuration> | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ | ||||||
| <head> | <head> | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <title>Labyrinth Generator</title> |     <title>Labyrinth Generator</title> | ||||||
|     <link rel="stylesheet" href="style.css"> |     <link href="style.css" rel="stylesheet"> | ||||||
| </head> | </head> | ||||||
| <body> | <body> | ||||||
| <div class="content"> | <div class="content"> | ||||||
|  | @ -11,8 +11,8 @@ | ||||||
|     <p>Enter some values, click the "Create!" button and see what happens!</p> |     <p>Enter some values, click the "Create!" button and see what happens!</p> | ||||||
|     <form action="/create" method="get"> |     <form action="/create" method="get"> | ||||||
|         <div class="inputs-wrapper"> |         <div class="inputs-wrapper"> | ||||||
|             <label for="width">Width:</label><input id="width" name="width" 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" name="height" type="number" min="1" required> |             <label for="height">Height:</label><input id="height" min="1" name="height" required type="number"> | ||||||
|             <label for="output">Output format:</label> |             <label for="output">Output format:</label> | ||||||
|             <select id="output" name="output" required> |             <select id="output" name="output" required> | ||||||
|                 <option label="HTML Document" value="html"></option> |                 <option label="HTML Document" value="html"></option> | ||||||
|  | @ -24,7 +24,7 @@ | ||||||
|             <label for="id">Seed (optional):</label><input id="id" name="id" type="number"> |             <label for="id">Seed (optional):</label><input id="id" name="id" type="number"> | ||||||
|         </div> |         </div> | ||||||
|         <div class="controls-wrapper"> |         <div class="controls-wrapper"> | ||||||
|             <button type="submit" class="primary">Create!</button> |             <button class="primary" type="submit">Create!</button> | ||||||
|             <button type="reset">Reset form</button> |             <button type="reset">Reset form</button> | ||||||
|         </div> |         </div> | ||||||
|     </form> |     </form> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue