feature/undertow #4
					 6 changed files with 202 additions and 191 deletions
				
			
		|  | @ -1,10 +1,11 @@ | ||||||
| package ch.fritteli.labyrinth.server; | package ch.fritteli.labyrinth.server; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | import ch.fritteli.labyrinth.server.handler.CreateHandler; | ||||||
| import ch.fritteli.labyrinth.generator.serialization.SerializerDeserializer; | import ch.fritteli.labyrinth.server.undertow_playground.LanyrinthRenderHandler; | ||||||
| import com.sun.net.httpserver.Headers; | import io.undertow.Undertow; | ||||||
| import com.sun.net.httpserver.HttpExchange; | import io.undertow.server.RoutingHandler; | ||||||
| import com.sun.net.httpserver.HttpServer; | import io.undertow.server.handlers.RedirectHandler; | ||||||
|  | import io.undertow.util.StatusCodes; | ||||||
| import io.vavr.collection.HashMap; | import io.vavr.collection.HashMap; | ||||||
| import io.vavr.collection.HashSet; | import io.vavr.collection.HashSet; | ||||||
| import io.vavr.collection.Map; | import io.vavr.collection.Map; | ||||||
|  | @ -16,28 +17,13 @@ import lombok.NonNull; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; |  | ||||||
| import java.io.OutputStream; |  | ||||||
| import java.net.InetSocketAddress; | import java.net.InetSocketAddress; | ||||||
| import java.nio.charset.StandardCharsets; |  | ||||||
| import java.util.concurrent.ExecutorService; |  | ||||||
| import java.util.concurrent.SynchronousQueue; |  | ||||||
| import java.util.concurrent.ThreadPoolExecutor; |  | ||||||
| import java.util.concurrent.TimeUnit; |  | ||||||
| import java.util.concurrent.atomic.AtomicBoolean; |  | ||||||
| import java.util.function.Function; | import java.util.function.Function; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class LabyrinthServer { | public class LabyrinthServer { | ||||||
|     @NonNull |     @NonNull | ||||||
|     private final HttpServer httpServer; |     private final Undertow undertow; | ||||||
|     @NonNull |  | ||||||
|     private final ExecutorService executorService = new ThreadPoolExecutor(0, |  | ||||||
|                                                                            1_000, |  | ||||||
|                                                                            5, |  | ||||||
|                                                                            TimeUnit.SECONDS, |  | ||||||
|                                                                            new SynchronousQueue<>() |  | ||||||
|     ); |  | ||||||
| 
 | 
 | ||||||
|     public static Option<LabyrinthServer> createAndStartServer() { |     public static Option<LabyrinthServer> createAndStartServer() { | ||||||
|         final Option<LabyrinthServer> serverOption = Try.of(ServerConfig::init) |         final Option<LabyrinthServer> serverOption = Try.of(ServerConfig::init) | ||||||
|  | @ -51,147 +37,106 @@ public class LabyrinthServer { | ||||||
|         return serverOption; |         return serverOption; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public LabyrinthServer(@NonNull final ServerConfig config) throws IOException { |     public LabyrinthServer(@NonNull final ServerConfig config) { | ||||||
|         this.httpServer = HttpServer.create(new InetSocketAddress(config.getAddress(), config.getPort()), 5); |         log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | ||||||
|         this.httpServer.createContext("/", new StaticResourcesFileHandler(this.executorService)); |         final RoutingHandler routingHandler = new RoutingHandler().get("/", new RedirectHandler("/create/text")) | ||||||
|         this.httpServer.createContext("/create", this::handleCreate); |                                                                   .get("/create", new RedirectHandler("/create/text")) | ||||||
|         this.httpServer.createContext("/render", this::handleRender); |                                                                   .get("/create/{output}", new CreateHandler()) | ||||||
|  |                                                                   .post("/render", new LanyrinthRenderHandler()) | ||||||
|  |                                                                   .setFallbackHandler(exchange -> { | ||||||
|  |                                                                       exchange.setStatusCode(StatusCodes.NOT_FOUND) | ||||||
|  |                                                                               .getResponseSender() | ||||||
|  |                                                                               .send("Resource %s not found".formatted( | ||||||
|  |                                                                                       exchange.getRequestURI())); | ||||||
|  |                                                                   }); | ||||||
|  |         this.undertow = Undertow.builder() | ||||||
|  |                                 .addHttpListener(config.getPort(), config.getAddress().getHostAddress()) | ||||||
|  |                                 .setHandler(routingHandler) | ||||||
|  |                                 .build(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void start() { |     public void start() { | ||||||
|         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); |         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); | ||||||
|         this.httpServer.start(); |         this.undertow.start(); | ||||||
|         log.info("Listening on http://{}:{}", |         Try.of(() -> (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress()) | ||||||
|                  this.httpServer.getAddress().getHostString(), |            .onFailure(e -> log.warn("Started server, unable to determine listeing address/port.")) | ||||||
|                  this.httpServer.getAddress().getPort() |            .forEach(address -> log.info("Listening on http://{}:{}", address.getHostString(), address.getPort())); | ||||||
|         ); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     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(); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     private void handleRender(final HttpExchange exchange) { |  | ||||||
|         this.executorService.submit(() -> { |  | ||||||
|             try { |  | ||||||
|                 log.debug("Handling request to {}", exchange.getRequestURI()); |  | ||||||
|                 final String requestMethod = exchange.getRequestMethod(); |  | ||||||
|                 if (!requestMethod.equals("POST")) { |  | ||||||
|                     exchange.getResponseBody().close(); |  | ||||||
|                     exchange.sendResponseHeaders(405, -1); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 final byte[] bytes = exchange.getRequestBody().readAllBytes(); |  | ||||||
| 
 |  | ||||||
|                 final Labyrinth labyrinth = SerializerDeserializer.deserialize(bytes); |  | ||||||
| 
 |  | ||||||
|                 final OutputType output = exchange.getRequestHeaders() |  | ||||||
|                                                   .get("Accept") |  | ||||||
|                                                   .contains(OutputType.HTML.getContentType()) ? |  | ||||||
|                                           OutputType.HTML : |  | ||||||
|                                           OutputType.TEXT_PLAIN; |  | ||||||
|                 final byte[] render; |  | ||||||
|                 final Headers responseHeaders = exchange.getResponseHeaders(); |  | ||||||
|                 try { |  | ||||||
|                     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).getBytes(StandardCharsets.UTF_8)); |  | ||||||
|                     responseBody.flush(); |  | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 responseHeaders.add("Content-type", output.getContentType()); |  | ||||||
|                 exchange.sendResponseHeaders(200, 0); |  | ||||||
|                 final OutputStream responseBody = exchange.getResponseBody(); |  | ||||||
|                 responseBody.write(render); |  | ||||||
|                 responseBody.flush(); |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 log.error("FSCK!", e); |  | ||||||
|             } finally { |  | ||||||
|                 exchange.close(); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void stop() { |     public void stop() { | ||||||
|         log.info("Stopping server ..."); |         log.info("Stopping server ..."); | ||||||
|         this.httpServer.stop(5); |         this.undertow.stop(); | ||||||
|         this.executorService.shutdown(); |  | ||||||
|         try { |  | ||||||
|             if (!this.executorService.awaitTermination(5, TimeUnit.SECONDS)) { |  | ||||||
|                 log.warn("Timeout occurred while awaiting termination of executor service"); |  | ||||||
|             } |  | ||||||
|         } catch (final InterruptedException e) { |  | ||||||
|             log.error("Failed to await termination of executor service", e); |  | ||||||
|         } |  | ||||||
|         log.info("Server stopped."); |         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 |     @NonNull | ||||||
|     private Map<RequestParameter, String> parseQueryString(@Nullable final String query) { |     private Map<RequestParameter, String> parseQueryString(@Nullable final String query) { | ||||||
|         if (query == null) { |         if (query == null) { | ||||||
|  | @ -218,15 +163,59 @@ public class LabyrinthServer { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private RequestParameter normalizeParameterName(final String paramName) { | ||||||
|  |         return RequestParameter.parseName(paramName).get(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     private <T> T getOrDefault(@NonNull final Option<String> input, |     private <T> T getOrDefault(@NonNull final Option<String> input, | ||||||
|                                @NonNull final Function<String, T> mapper, |                                @NonNull final Function<String, T> mapper, | ||||||
|                                @Nullable final T defaultValue) { |                                @Nullable final T defaultValue) { | ||||||
|         return input.toTry().map(mapper).getOrElse(defaultValue); |         return input.toTry().map(mapper).getOrElse(defaultValue); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private RequestParameter normalizeParameterName(final String paramName) { | //    private void handleRender(final HttpExchange exchange) { | ||||||
|         return RequestParameter.parseName(paramName).get(); | //        this.executorService.submit(() -> { | ||||||
|     } | //            try { | ||||||
|  | //                log.debug("Handling request to {}", exchange.getRequestURI()); | ||||||
|  | //                final String requestMethod = exchange.getRequestMethod(); | ||||||
|  | //                if (!requestMethod.equals("POST")) { | ||||||
|  | //                    exchange.getResponseBody().close(); | ||||||
|  | //                    exchange.sendResponseHeaders(405, -1); | ||||||
|  | //                    return; | ||||||
|  | //                } | ||||||
|  | //                final byte[] bytes = exchange.getRequestBody().readAllBytes(); | ||||||
|  | // | ||||||
|  | //                final Labyrinth labyrinth = SerializerDeserializer.deserialize(bytes); | ||||||
|  | // | ||||||
|  | //                final OutputType output = exchange.getRequestHeaders() | ||||||
|  | //                                                  .get("Accept") | ||||||
|  | //                                                  .contains(OutputType.HTML.getContentType()) ? | ||||||
|  | //                                          OutputType.HTML : | ||||||
|  | //                                          OutputType.TEXT_PLAIN; | ||||||
|  | //                final byte[] render; | ||||||
|  | //                final Headers responseHeaders = exchange.getResponseHeaders(); | ||||||
|  | //                try { | ||||||
|  | //                    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).getBytes(StandardCharsets.UTF_8)); | ||||||
|  | //                    responseBody.flush(); | ||||||
|  | //                    return; | ||||||
|  | //                } | ||||||
|  | //                responseHeaders.add("Content-type", output.getContentType()); | ||||||
|  | //                exchange.sendResponseHeaders(200, 0); | ||||||
|  | //                final OutputStream responseBody = exchange.getResponseBody(); | ||||||
|  | //                responseBody.write(render); | ||||||
|  | //                responseBody.flush(); | ||||||
|  | //            } catch (Exception e) { | ||||||
|  | //                log.error("FSCK!", e); | ||||||
|  | //            } finally { | ||||||
|  | //                exchange.close(); | ||||||
|  | //            } | ||||||
|  | //        }); | ||||||
|  | //    } | ||||||
| 
 | 
 | ||||||
|     private enum RequestParameter { |     private enum RequestParameter { | ||||||
|         WIDTH("w", "width"), |         WIDTH("w", "width"), | ||||||
|  |  | ||||||
|  | @ -1,21 +1,18 @@ | ||||||
| package ch.fritteli.labyrinth.server; | package ch.fritteli.labyrinth.server; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.labyrinth.server.undertow_playground.UndertowPlayground; |  | ||||||
| import io.undertow.Undertow; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class Main { | public class Main { | ||||||
|     public static void main(String[] args) { |     public static void main(String[] args) { | ||||||
| //        LabyrinthServer.createAndStartServer() |         LabyrinthServer.createAndStartServer().onEmpty(() -> log.error("Failed to create server. Stopping.")); | ||||||
| //                .onEmpty(() -> log.error("Failed to create server. Stopping.")); |  | ||||||
| 
 | 
 | ||||||
|         final ServerConfig config = ServerConfig.init(); | //        final ServerConfig config = ServerConfig.init(); | ||||||
|         log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | //        log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | ||||||
|         Undertow.builder() | //        Undertow.builder() | ||||||
|                 .addHttpListener(config.getPort(), config.getAddress().getHostAddress()) | //                .addHttpListener(config.getPort(), config.getAddress().getHostAddress()) | ||||||
|                 .setHandler(UndertowPlayground.r) | //                .setHandler(UndertowPlayground.r) | ||||||
|                 .build() | //                .build() | ||||||
|                 .start(); | //                .start(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | package ch.fritteli.labyrinth.server.handler; | ||||||
|  | 
 | ||||||
|  | import io.undertow.server.HttpHandler; | ||||||
|  | import io.undertow.server.HttpServerExchange; | ||||||
|  | import io.undertow.util.StatusCodes; | ||||||
|  | import lombok.NonNull; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | 
 | ||||||
|  | @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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected abstract void handle(@NonNull final HttpServerExchange exchange) throws Exception; | ||||||
|  | } | ||||||
|  | @ -1,12 +1,14 @@ | ||||||
| package ch.fritteli.labyrinth.server.undertow_playground; | package ch.fritteli.labyrinth.server.handler; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | import ch.fritteli.labyrinth.generator.model.Labyrinth; | ||||||
| import ch.fritteli.labyrinth.server.OutputType; | import ch.fritteli.labyrinth.server.OutputType; | ||||||
| import io.undertow.server.HttpHandler; | import ch.fritteli.labyrinth.server.handler.AbstractHttpHandler; | ||||||
|  | import ch.fritteli.labyrinth.server.undertow_playground.UndertowPlayground; | ||||||
| import io.undertow.server.HttpServerExchange; | import io.undertow.server.HttpServerExchange; | ||||||
| import io.undertow.util.Headers; | import io.undertow.util.Headers; | ||||||
| import io.undertow.util.HttpString; | import io.undertow.util.HttpString; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
|  | import lombok.NonNull; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| 
 | 
 | ||||||
| import java.nio.ByteBuffer; | import java.nio.ByteBuffer; | ||||||
|  | @ -15,13 +17,9 @@ import java.util.Map; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| class LabyrinthHttpHandler implements HttpHandler { | public class CreateHandler extends AbstractHttpHandler { | ||||||
|     @Override |     @Override | ||||||
|     public void handleRequest(HttpServerExchange exchange) throws Exception { |     protected void handle(@NonNull final HttpServerExchange exchange) throws Exception { | ||||||
|         if (exchange.isInIoThread()) { |  | ||||||
|             exchange.dispatch(this); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); |         final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); | ||||||
|         final Option<String> output = UndertowPlayground.getFirstOption(queryParameters, "output"); |         final Option<String> output = UndertowPlayground.getFirstOption(queryParameters, "output"); | ||||||
|         final Option<Integer> width = UndertowPlayground.getIntOption(queryParameters, "width"); |         final Option<Integer> width = UndertowPlayground.getIntOption(queryParameters, "width"); | ||||||
|  | @ -0,0 +1,17 @@ | ||||||
|  | package ch.fritteli.labyrinth.server.undertow_playground; | ||||||
|  | 
 | ||||||
|  | import io.undertow.server.HttpHandler; | ||||||
|  | import io.undertow.server.HttpServerExchange; | ||||||
|  | import io.undertow.util.StatusCodes; | ||||||
|  | 
 | ||||||
|  | public class LanyrinthRenderHandler implements HttpHandler { | ||||||
|  |     @Override | ||||||
|  |     public void handleRequest(final HttpServerExchange exchange) { | ||||||
|  |         if (exchange.isInIoThread()) { | ||||||
|  |             exchange.dispatch(this); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         exchange.setStatusCode(StatusCodes.NOT_IMPLEMENTED); | ||||||
|  |         exchange.getResponseSender().send("Rendering binary data is not implemented yet."); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -14,24 +14,6 @@ import java.util.Map; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class UndertowPlayground { | public class UndertowPlayground { | ||||||
|     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()) { |  | ||||||
|                 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 |     @NonNull | ||||||
|     public 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) { |                                                 @NonNull final String paramName) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue