feature/undertow #4
					 4 changed files with 125 additions and 109 deletions
				
			
		|  | @ -1,22 +1,17 @@ | |||
| package ch.fritteli.labyrinth.server; | ||||
| 
 | ||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | ||||
| import ch.fritteli.labyrinth.generator.renderer.html.HTMLRenderer; | ||||
| import ch.fritteli.labyrinth.generator.renderer.pdf.PDFRenderer; | ||||
| import ch.fritteli.labyrinth.generator.renderer.text.TextRenderer; | ||||
| import ch.fritteli.labyrinth.generator.serialization.SerializerDeserializer; | ||||
| import com.sun.net.httpserver.Headers; | ||||
| import com.sun.net.httpserver.HttpExchange; | ||||
| import com.sun.net.httpserver.HttpServer; | ||||
| import io.vavr.collection.HashMap; | ||||
| import io.vavr.collection.HashSet; | ||||
| import io.vavr.collection.List; | ||||
| import io.vavr.collection.Map; | ||||
| import io.vavr.collection.Set; | ||||
| import io.vavr.collection.Stream; | ||||
| import io.vavr.control.Option; | ||||
| import io.vavr.control.Try; | ||||
| import lombok.Getter; | ||||
| import lombok.NonNull; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
|  | @ -251,71 +246,4 @@ public class LabyrinthServer { | |||
|             return Stream.of(values()).find(param -> param.names.exists(name::equalsIgnoreCase)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public enum OutputType { | ||||
|         TEXT_PLAIN("text/plain; charset=UTF-8", | ||||
|                    labyrinth -> TextRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), | ||||
|                    "txt", | ||||
|                    false, | ||||
|                    "t", | ||||
|                    "text" | ||||
|         ), | ||||
|         HTML("text/html", | ||||
|              labyrinth -> HTMLRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), | ||||
|              "html", | ||||
|              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"); | ||||
|         @Getter | ||||
|         @NonNull | ||||
|         private final String contentType; | ||||
|         @NonNull | ||||
|         private final List<String> names; | ||||
|         @NonNull | ||||
|         private final Function<Labyrinth, byte[]> render; | ||||
|         @Getter | ||||
|         private final boolean attachment; | ||||
|         @Getter | ||||
|         @NonNull | ||||
|         private final String fileExtension; | ||||
| 
 | ||||
|         OutputType(@NonNull final String contentType, | ||||
|                    @NonNull final Function<Labyrinth, byte[]> render, | ||||
|                    @NonNull final String fileExtension, | ||||
|                    final boolean attachment, | ||||
|                    @NonNull final String... names) { | ||||
|             this.contentType = contentType; | ||||
|             this.render = render; | ||||
|             this.fileExtension = fileExtension; | ||||
|             this.attachment = attachment; | ||||
|             this.names = List.of(names); | ||||
|         } | ||||
| 
 | ||||
|         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)); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public String toString() { | ||||
|             return this.names.last(); | ||||
|         } | ||||
| 
 | ||||
|         public byte[] render(@NonNull final Labyrinth labyrinth) { | ||||
|             return this.render.apply(labyrinth); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										77
									
								
								src/main/java/ch/fritteli/labyrinth/server/OutputType.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/main/java/ch/fritteli/labyrinth/server/OutputType.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| package ch.fritteli.labyrinth.server; | ||||
| 
 | ||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | ||||
| import ch.fritteli.labyrinth.generator.renderer.html.HTMLRenderer; | ||||
| import ch.fritteli.labyrinth.generator.renderer.pdf.PDFRenderer; | ||||
| import ch.fritteli.labyrinth.generator.renderer.text.TextRenderer; | ||||
| import ch.fritteli.labyrinth.generator.serialization.SerializerDeserializer; | ||||
| import io.vavr.collection.List; | ||||
| import io.vavr.collection.Stream; | ||||
| import io.vavr.control.Option; | ||||
| import lombok.Getter; | ||||
| import lombok.NonNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| 
 | ||||
| import java.nio.charset.StandardCharsets; | ||||
| 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", | ||||
|                false, | ||||
|                "t", | ||||
|                "text" | ||||
|     ), | ||||
|     HTML("text/html", | ||||
|          labyrinth -> HTMLRenderer.newInstance().render(labyrinth).getBytes(StandardCharsets.UTF_8), | ||||
|          "html", | ||||
|          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"); | ||||
|     @Getter | ||||
|     @NonNull | ||||
|     private final String contentType; | ||||
|     @NonNull | ||||
|     private final List<String> names; | ||||
|     @NonNull | ||||
|     private final Function<Labyrinth, byte[]> render; | ||||
|     @Getter | ||||
|     private final boolean attachment; | ||||
|     @Getter | ||||
|     @NonNull | ||||
|     private final String fileExtension; | ||||
| 
 | ||||
|     OutputType(@NonNull final String contentType, | ||||
|                @NonNull final Function<Labyrinth, byte[]> render, | ||||
|                @NonNull final String fileExtension, | ||||
|                final boolean attachment, | ||||
|                @NonNull final String... names) { | ||||
|         this.contentType = contentType; | ||||
|         this.render = render; | ||||
|         this.fileExtension = fileExtension; | ||||
|         this.attachment = attachment; | ||||
|         this.names = List.of(names); | ||||
|     } | ||||
| 
 | ||||
|     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)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return this.names.last(); | ||||
|     } | ||||
| 
 | ||||
|     public byte[] render(@NonNull final Labyrinth labyrinth) { | ||||
|         return this.render.apply(labyrinth); | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,45 @@ | |||
| package ch.fritteli.labyrinth.server.undertow_playground; | ||||
| 
 | ||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | ||||
| import ch.fritteli.labyrinth.server.OutputType; | ||||
| import io.undertow.server.HttpHandler; | ||||
| import io.undertow.server.HttpServerExchange; | ||||
| import io.undertow.util.Headers; | ||||
| import io.undertow.util.HttpString; | ||||
| import io.vavr.control.Option; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| import java.nio.ByteBuffer; | ||||
| import java.util.Deque; | ||||
| import java.util.Map; | ||||
| import java.util.Random; | ||||
| 
 | ||||
| @Slf4j | ||||
| class LabyrinthHttpHandler implements 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 = UndertowPlayground.getFirstOption(queryParameters, "output"); | ||||
|         final Option<Integer> width = UndertowPlayground.getIntOption(queryParameters, "width"); | ||||
|         final Option<Integer> height = UndertowPlayground.getIntOption(queryParameters, "height"); | ||||
|         final Option<Integer> id = UndertowPlayground.getIntOption(queryParameters, "id"); | ||||
| 
 | ||||
|         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 OutputType outputType = output.flatMap(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)); | ||||
|     } | ||||
| } | ||||
|  | @ -1,54 +1,20 @@ | |||
| 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; | ||||
| import io.undertow.util.HeaderValues; | ||||
| import io.undertow.util.Headers; | ||||
| import io.undertow.util.HttpString; | ||||
| 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"); | ||||
| 
 | ||||
|             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() { | ||||
|     public static final RoutingHandler r = new RoutingHandler().get("/create/{output}", new LabyrinthHttpHandler()).post("/render", new HttpHandler() { | ||||
|         @Override | ||||
|         public void handleRequest(final HttpServerExchange exchange) { | ||||
|             if (exchange.isInIoThread()) { | ||||
|  | @ -67,13 +33,13 @@ public class UndertowPlayground { | |||
|     }); | ||||
| 
 | ||||
|     @NonNull | ||||
|     private static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, | ||||
|     public 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<String> getFirstOption(@NonNull final Map<String, Deque<String>> queryParams, | ||||
|     public 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); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue