From cfc80d88be3569512bc910edf717c037063650ca Mon Sep 17 00:00:00 2001 From: joshua bauer Date: Mon, 5 Mar 2018 09:45:56 -0800 Subject: [PATCH] Improve response and request error handling. --- .../sinistral/proteus/ProteusApplication.java | 16 +++ .../sinistral/proteus/server/Extractors.java | 15 +-- .../proteus/server/ServerRequest.java | 4 +- .../proteus/server/ServerResponse.java | 35 +++++ .../proteus/utilities/TablePrinter.java | 127 ++++++++++++++++++ 5 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 src/main/java/io/sinistral/proteus/utilities/TablePrinter.java diff --git a/src/main/java/io/sinistral/proteus/ProteusApplication.java b/src/main/java/io/sinistral/proteus/ProteusApplication.java index aaacf74..ae82fa6 100644 --- a/src/main/java/io/sinistral/proteus/ProteusApplication.java +++ b/src/main/java/io/sinistral/proteus/ProteusApplication.java @@ -13,6 +13,7 @@ import java.nio.file.Paths; import java.security.KeyStore; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; @@ -46,6 +47,7 @@ import io.sinistral.proteus.server.handlers.HandlerGenerator; import io.sinistral.proteus.server.handlers.ServerDefaultHttpHandler; import io.sinistral.proteus.utilities.SecurityOps; +import io.sinistral.proteus.utilities.TablePrinter; import io.undertow.Undertow; import io.undertow.Undertow.ListenerInfo; import io.undertow.UndertowOptions; @@ -382,7 +384,21 @@ public void printStatus() sb.append("\n\nUsing global headers: \n\n"); sb.append(globalHeadersParameters.entrySet().stream().map(e -> "\t" + e.getKey() + " = " + e.getValue()).collect(Collectors.joining("\n"))); sb.append("\n\nRegistered endpoints: \n\n"); + + List tableHeaders = Arrays.asList("Method","Path","Consumes","Produces","Controller"); + + List> tableRows = this.registeredEndpoints.stream().sorted().map( e -> { + + return Arrays.asList( e.getMethod().toString(), e.getPathTemplate(), String.format("[%s]", e.getConsumes()), String.format("[%s]", e.getProduces()), String.format("(%s.%s)", e.getControllerName() , e.getControllerMethod() ) ); + + }).collect(Collectors.toList()); + + TablePrinter printer = new TablePrinter(tableHeaders, tableRows); + + sb.append(printer.toString()); + sb.append(this.registeredEndpoints.stream().sorted().map(EndpointInfo::toString).collect(Collectors.joining("\n"))); + sb.append("\n\nRegistered services: \n\n"); ImmutableMultimap serviceStateMap = this.serviceManager.servicesByState(); diff --git a/src/main/java/io/sinistral/proteus/server/Extractors.java b/src/main/java/io/sinistral/proteus/server/Extractors.java index 5ae6922..af3f3b5 100644 --- a/src/main/java/io/sinistral/proteus/server/Extractors.java +++ b/src/main/java/io/sinistral/proteus/server/Extractors.java @@ -197,14 +197,13 @@ public static java.util.Optional string(final HttpServerExchange exchan public static java.util.Optional filePath(final HttpServerExchange exchange, final String name) { - return java.util.Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map( fv -> fv.getFile().toPath()); + return java.util.Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map( fv -> fv.getPath()); } public static java.util.Optional byteBuffer(final HttpServerExchange exchange, final String name) { return Optional.filePath(exchange,name).map( fp -> { - - + try(final FileChannel fileChannel = FileChannel.open(fp, StandardOpenOption.READ)) { final ByteBuffer buffer = ByteBuffer.allocate((int)fileChannel.size()); @@ -219,11 +218,7 @@ public static java.util.Optional byteBuffer(final HttpServerExchang { return null; } - }); - - - } } @@ -233,9 +228,7 @@ public static String string(final HttpServerExchange exchange, final String nam { try { - return exchange.getRequestHeaders().get(name).getFirst(); - } catch(NullPointerException e) { throw new IllegalArgumentException("Missing parameter " + name, e); @@ -468,6 +461,10 @@ else if( a instanceof javax.ws.rs.OPTIONS) { return Methods.OPTIONS; } + else if( a instanceof javax.ws.rs.HEAD) + { + return Methods.HEAD; + } else { diff --git a/src/main/java/io/sinistral/proteus/server/ServerRequest.java b/src/main/java/io/sinistral/proteus/server/ServerRequest.java index f281b23..071a3dc 100644 --- a/src/main/java/io/sinistral/proteus/server/ServerRequest.java +++ b/src/main/java/io/sinistral/proteus/server/ServerRequest.java @@ -152,9 +152,9 @@ private void extractBytes() throws IOException final StreamSourceChannel channel = this.exchange.getRequestChannel(); while (true) { + + buf.clear(); - buf.clear(); - int c = channel.read(buf); if (c == -1) { diff --git a/src/main/java/io/sinistral/proteus/server/ServerResponse.java b/src/main/java/io/sinistral/proteus/server/ServerResponse.java index 6e1d9d6..f88ad6d 100644 --- a/src/main/java/io/sinistral/proteus/server/ServerResponse.java +++ b/src/main/java/io/sinistral/proteus/server/ServerResponse.java @@ -262,12 +262,26 @@ public ServerResponse badRequest() this.status = StatusCodes.BAD_REQUEST; return this; } + + public ServerResponse badRequest(Throwable t) + { + this.status = StatusCodes.BAD_REQUEST; + this.throwable = t; + return this; + } public ServerResponse internalServerError() { this.status = StatusCodes.INTERNAL_SERVER_ERROR; return this; } + + public ServerResponse internalServerError(Throwable t) + { + this.status = StatusCodes.INTERNAL_SERVER_ERROR; + this.throwable = t; + return this; + } public ServerResponse created() { @@ -280,12 +294,26 @@ public ServerResponse notFound() this.status = StatusCodes.NOT_FOUND; return this; } + + public ServerResponse notFound(Throwable t) + { + this.status = StatusCodes.NOT_FOUND; + this.throwable = t; + return this; + } public ServerResponse forbidden() { this.status = StatusCodes.FORBIDDEN; return this; } + + public ServerResponse forbidden(Throwable t) + { + this.status = StatusCodes.FORBIDDEN; + this.throwable = t; + return this; + } public ServerResponse found() { @@ -298,6 +326,13 @@ public ServerResponse noContent() this.status = StatusCodes.NO_CONTENT; return this; } + + public ServerResponse noContent(Throwable t) + { + this.status = StatusCodes.NO_CONTENT; + this.throwable = t; + return this; + } public ServerResponse withIoCallback(IoCallback ioCallback) { diff --git a/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java b/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java new file mode 100644 index 0000000..069b716 --- /dev/null +++ b/src/main/java/io/sinistral/proteus/utilities/TablePrinter.java @@ -0,0 +1,127 @@ +/** + * + */ +package io.sinistral.proteus.utilities; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author jbauer + */ +public class TablePrinter +{ + private final int TABLEPADDING = 4; + + + private List headers; + private List> table; + private List maxLength; + + public TablePrinter(List headersIn, List> content) + { + this.headers = headersIn; + this.maxLength = new ArrayList(); + for (int i = 0; i < headers.size(); i++) + { + maxLength.add(headers.get(i).length()); + } + this.table = content; + + updateMaxLengths(); + } + + public void updateField(int row, int col, String input) + { + table.get(row).set(col, input); + updateMaxColumnLength(col); + } + + + public String toString() + { + StringBuilder sb = new StringBuilder(); + StringBuilder rowSeparatorBuilder = new StringBuilder(); + String padder = ""; + String rowSeperator = ""; + + for (int i = 0; i < 4; i++) + { + padder += " "; + } + + for (int i = 0; i < maxLength.size(); i++) + { + for (int j = 0; j < maxLength.get(i) + (TABLEPADDING * 2); j++) + { + rowSeparatorBuilder.append("-"); + } + } + + rowSeperator = rowSeparatorBuilder.toString(); + + sb.append("\n"); + + for (int i = 0; i < headers.size(); i++) + { + sb.append(padder); + sb.append(headers.get(i)); + for (int k = 0; k < (maxLength.get(i) - headers.get(i).length()); k++) + { + sb.append(" "); + } + sb.append(padder); + } + + sb.append("\n"); + sb.append(rowSeperator); + sb.append("\n"); + + for (int i = 0; i < table.size(); i++) + { + List tempRow = table.get(i); + for (int j = 0; j < tempRow.size(); j++) + { + sb.append(padder); + sb.append(tempRow.get(j)); + for (int k = 0; k < (maxLength.get(j) - tempRow.get(j).length()); k++) + { + sb.append(" "); + } + sb.append(padder); + } + sb.append("\n"); + } + + return sb.toString(); + } + + private void updateMaxLengths() + { + for (int i = 0; i < table.size(); i++) + { + List temp = table.get(i); + for (int j = 0; j < temp.size(); j++) + { + if (temp.get(j).length() > maxLength.get(j)) + { + maxLength.set(j, temp.get(j).length()); + } + } + } + } + + private void updateMaxColumnLength(int col) + { + for (int i = 0; i < table.size(); i++) + { + if (table.get(i).get(col).length() > maxLength.get(col)) + { + maxLength.set(col, table.get(i).get(col).length()); + } + } + } + +}