This commit is contained in:
		
							parent
							
								
									65421caf85
								
							
						
					
					
						commit
						dd571a190a
					
				
					 6 changed files with 202 additions and 191 deletions
				
			
		|  | @ -1,10 +1,11 @@ | |||
| package ch.fritteli.labyrinth.server; | ||||
| 
 | ||||
| import ch.fritteli.labyrinth.generator.model.Labyrinth; | ||||
| 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 ch.fritteli.labyrinth.server.handler.CreateHandler; | ||||
| import ch.fritteli.labyrinth.server.undertow_playground.LanyrinthRenderHandler; | ||||
| import io.undertow.Undertow; | ||||
| import io.undertow.server.RoutingHandler; | ||||
| import io.undertow.server.handlers.RedirectHandler; | ||||
| import io.undertow.util.StatusCodes; | ||||
| import io.vavr.collection.HashMap; | ||||
| import io.vavr.collection.HashSet; | ||||
| import io.vavr.collection.Map; | ||||
|  | @ -16,28 +17,13 @@ import lombok.NonNull; | |||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
| 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; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class LabyrinthServer { | ||||
|     @NonNull | ||||
|     private final HttpServer httpServer; | ||||
|     @NonNull | ||||
|     private final ExecutorService executorService = new ThreadPoolExecutor(0, | ||||
|                                                                            1_000, | ||||
|                                                                            5, | ||||
|                                                                            TimeUnit.SECONDS, | ||||
|                                                                            new SynchronousQueue<>() | ||||
|     ); | ||||
|     private final Undertow undertow; | ||||
| 
 | ||||
|     public static Option<LabyrinthServer> createAndStartServer() { | ||||
|         final Option<LabyrinthServer> serverOption = Try.of(ServerConfig::init) | ||||
|  | @ -51,147 +37,106 @@ public class LabyrinthServer { | |||
|         return serverOption; | ||||
|     } | ||||
| 
 | ||||
|     public LabyrinthServer(@NonNull final ServerConfig config) throws IOException { | ||||
|         this.httpServer = HttpServer.create(new InetSocketAddress(config.getAddress(), config.getPort()), 5); | ||||
|         this.httpServer.createContext("/", new StaticResourcesFileHandler(this.executorService)); | ||||
|         this.httpServer.createContext("/create", this::handleCreate); | ||||
|         this.httpServer.createContext("/render", this::handleRender); | ||||
|     public LabyrinthServer(@NonNull final ServerConfig config) { | ||||
|         log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | ||||
|         final RoutingHandler routingHandler = new RoutingHandler().get("/", new RedirectHandler("/create/text")) | ||||
|                                                                   .get("/create", new RedirectHandler("/create/text")) | ||||
|                                                                   .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() { | ||||
|         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); | ||||
|         this.httpServer.start(); | ||||
|         log.info("Listening on http://{}:{}", | ||||
|                  this.httpServer.getAddress().getHostString(), | ||||
|                  this.httpServer.getAddress().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(); | ||||
|             } | ||||
|         }); | ||||
|         this.undertow.start(); | ||||
|         Try.of(() -> (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress()) | ||||
|            .onFailure(e -> log.warn("Started server, unable to determine listeing address/port.")) | ||||
|            .forEach(address -> log.info("Listening on http://{}:{}", address.getHostString(), address.getPort())); | ||||
|     } | ||||
| 
 | ||||
|     public void stop() { | ||||
|         log.info("Stopping server ..."); | ||||
|         this.httpServer.stop(5); | ||||
|         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); | ||||
|         } | ||||
|         this.undertow.stop(); | ||||
|         log.info("Server stopped."); | ||||
|     } | ||||
| 
 | ||||
| //    private void handleCreate(HttpExchange exchange) { | ||||
| //        this.executorService.submit(() -> { | ||||
| //            log.debug("Handling request to {}", exchange.getRequestURI()); | ||||
| //            try { | ||||
| //                final String requestMethod = exchange.getRequestMethod(); | ||||
| //                if (!requestMethod.equals("GET")) { | ||||
| //                    exchange.getResponseBody().close(); | ||||
| //                    exchange.sendResponseHeaders(405, -1); | ||||
| //                    return; | ||||
| //                } | ||||
| //                final Map<RequestParameter, String> requestParams = this.parseQueryString(exchange.getRequestURI() | ||||
| //                                                                                                  .getQuery()); | ||||
| //                final int width = this.getOrDefault(requestParams.get(RequestParameter.WIDTH), Integer::valueOf, 5); | ||||
| //                final int height = this.getOrDefault(requestParams.get(RequestParameter.HEIGHT), Integer::valueOf, 7); | ||||
| //                final Option<Long> idOption = requestParams.get(RequestParameter.ID) | ||||
| //                                                           .toTry() | ||||
| //                                                           .map(Long::valueOf) | ||||
| //                                                           .toOption(); | ||||
| //                final Option<OutputType> outputOption = requestParams.get(RequestParameter.OUTPUT) | ||||
| //                                                                     .flatMap(OutputType::ofString); | ||||
| //                final Headers responseHeaders = exchange.getResponseHeaders(); | ||||
| //                final AtomicBoolean needsRedirect = new AtomicBoolean(false); | ||||
| //                final long id = idOption.onEmpty(() -> needsRedirect.set(true)).getOrElse(System::nanoTime); | ||||
| //                final OutputType output = outputOption.onEmpty(() -> needsRedirect.set(true)) | ||||
| //                                                      .getOrElse(OutputType.HTML); | ||||
| //                if (needsRedirect.get()) { | ||||
| //                    responseHeaders.add("Location", | ||||
| //                                        "create?width=" + width + "&height=" + height + "&output=" + output | ||||
| //                                        .toString() + | ||||
| //                                        "&id=" + id | ||||
| //                    ); | ||||
| //                    exchange.sendResponseHeaders(302, -1); | ||||
| //                    return; | ||||
| //                } | ||||
| //                final byte[] render; | ||||
| //                try { | ||||
| //                    final Labyrinth labyrinth = new Labyrinth(width, height, id); | ||||
| //                    render = output.render(labyrinth); | ||||
| //                } catch (Exception e) { | ||||
| //                    responseHeaders.add("Content-type", "text/plain; charset=UTF-8"); | ||||
| //                    exchange.sendResponseHeaders(500, 0); | ||||
| //                    final OutputStream responseBody = exchange.getResponseBody(); | ||||
| //                    responseBody.write(("Error: " + e.getMessage()).getBytes(StandardCharsets.UTF_8)); | ||||
| //                    responseBody.flush(); | ||||
| //                    return; | ||||
| //                } | ||||
| //                responseHeaders.add("Content-type", output.getContentType()); | ||||
| //                if (output.isAttachment()) { | ||||
| //                    responseHeaders.add("Content-disposition", String.format( | ||||
| //                            "attachment; filename=\"labyrinth-%dx%d-%d.%s\"", | ||||
| //                            width, | ||||
| //                            height, | ||||
| //                            id, | ||||
| //                            output.getFileExtension() | ||||
| //                    )); | ||||
| //                } | ||||
| //                exchange.sendResponseHeaders(200, 0); | ||||
| //                final OutputStream responseBody = exchange.getResponseBody(); | ||||
| //                responseBody.write(render); | ||||
| //                responseBody.flush(); | ||||
| //            } catch (Exception e) { | ||||
| //                log.error("FSCK!", e); | ||||
| //            } finally { | ||||
| //                exchange.close(); | ||||
| //            } | ||||
| //        }); | ||||
| //    } | ||||
| 
 | ||||
|     @NonNull | ||||
|     private Map<RequestParameter, String> parseQueryString(@Nullable final String query) { | ||||
|         if (query == null) { | ||||
|  | @ -218,15 +163,59 @@ public class LabyrinthServer { | |||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     private RequestParameter normalizeParameterName(final String paramName) { | ||||
|         return RequestParameter.parseName(paramName).get(); | ||||
|     } | ||||
| 
 | ||||
|     private <T> T getOrDefault(@NonNull final Option<String> input, | ||||
|                                @NonNull final Function<String, T> mapper, | ||||
|                                @Nullable final T defaultValue) { | ||||
|         return input.toTry().map(mapper).getOrElse(defaultValue); | ||||
|     } | ||||
| 
 | ||||
|     private RequestParameter normalizeParameterName(final String paramName) { | ||||
|         return RequestParameter.parseName(paramName).get(); | ||||
|     } | ||||
| //    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(); | ||||
| //            } | ||||
| //        }); | ||||
| //    } | ||||
| 
 | ||||
|     private enum RequestParameter { | ||||
|         WIDTH("w", "width"), | ||||
|  |  | |||
|  | @ -1,21 +1,18 @@ | |||
| package ch.fritteli.labyrinth.server; | ||||
| 
 | ||||
| import ch.fritteli.labyrinth.server.undertow_playground.UndertowPlayground; | ||||
| import io.undertow.Undertow; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| @Slf4j | ||||
| public class Main { | ||||
|     public static void main(String[] args) { | ||||
| //        LabyrinthServer.createAndStartServer() | ||||
| //                .onEmpty(() -> log.error("Failed to create server. Stopping.")); | ||||
|         LabyrinthServer.createAndStartServer().onEmpty(() -> log.error("Failed to create server. Stopping.")); | ||||
| 
 | ||||
|         final ServerConfig config = ServerConfig.init(); | ||||
|         log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | ||||
|         Undertow.builder() | ||||
|                 .addHttpListener(config.getPort(), config.getAddress().getHostAddress()) | ||||
|                 .setHandler(UndertowPlayground.r) | ||||
|                 .build() | ||||
|                 .start(); | ||||
| //        final ServerConfig config = ServerConfig.init(); | ||||
| //        log.info("Starting Server at http://{}:{}/", config.getAddress().getHostAddress(), config.getPort()); | ||||
| //        Undertow.builder() | ||||
| //                .addHttpListener(config.getPort(), config.getAddress().getHostAddress()) | ||||
| //                .setHandler(UndertowPlayground.r) | ||||
| //                .build() | ||||
| //                .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.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.util.Headers; | ||||
| import io.undertow.util.HttpString; | ||||
| import io.vavr.control.Option; | ||||
| import lombok.NonNull; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| 
 | ||||
| import java.nio.ByteBuffer; | ||||
|  | @ -15,13 +17,9 @@ import java.util.Map; | |||
| import java.util.Random; | ||||
| 
 | ||||
| @Slf4j | ||||
| class LabyrinthHttpHandler implements HttpHandler { | ||||
| public class CreateHandler extends AbstractHttpHandler { | ||||
|     @Override | ||||
|     public void handleRequest(HttpServerExchange exchange) throws Exception { | ||||
|         if (exchange.isInIoThread()) { | ||||
|             exchange.dispatch(this); | ||||
|             return; | ||||
|         } | ||||
|     protected void handle(@NonNull final HttpServerExchange exchange) throws Exception { | ||||
|         final Map<String, Deque<String>> queryParameters = exchange.getQueryParameters(); | ||||
|         final Option<String> output = UndertowPlayground.getFirstOption(queryParameters, "output"); | ||||
|         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 | ||||
| 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 | ||||
|     public static Option<Integer> getIntOption(@NonNull final Map<String, Deque<String>> queryParams, | ||||
|                                                 @NonNull final String paramName) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue