From 6c0ae6cb4017ffe99aefb3f6640d5bb733b342d4 Mon Sep 17 00:00:00 2001 From: joshua bauer Date: Fri, 31 Mar 2017 16:58:35 -0700 Subject: [PATCH] ~70k posts/sec --- src/com/wurrly/BaseServer.java | 4 +- src/com/wurrly/controllers/Users.java | 42 ++- src/com/wurrly/models/User.java | 33 +++ src/com/wurrly/server/Extractors.java | 156 ++++++++++ .../{utilities => server}/ServerRequest.java | 138 ++++++--- src/com/wurrly/server/ServerResponse.java | 13 + src/com/wurrly/tests/TestGenerator.java | 2 +- src/com/wurrly/tests/TestInvoker.java | 3 +- src/com/wurrly/utilities/HandleGenerator.java | 279 +++++++++++------- 9 files changed, 512 insertions(+), 158 deletions(-) create mode 100644 src/com/wurrly/server/Extractors.java rename src/com/wurrly/{utilities => server}/ServerRequest.java (57%) create mode 100644 src/com/wurrly/server/ServerResponse.java diff --git a/src/com/wurrly/BaseServer.java b/src/com/wurrly/BaseServer.java index 787b782..a2a449c 100644 --- a/src/com/wurrly/BaseServer.java +++ b/src/com/wurrly/BaseServer.java @@ -24,8 +24,8 @@ import com.wurrly.controllers.Users; import com.wurrly.models.User; import com.wurrly.modules.DIModule; +import com.wurrly.server.ServerRequest; import com.wurrly.utilities.HandleGenerator; -import com.wurrly.utilities.ServerRequest; import io.undertow.Undertow; import io.undertow.UndertowOptions; @@ -206,7 +206,7 @@ public void handleRequest(HttpServerExchange exchange) throws Exception .setSocketOption(org.xnio.Options.BACKLOG, 10000) .setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false) - .setWorkerThreads(Runtime.getRuntime().availableProcessors() * 2) + .setWorkerThreads(Runtime.getRuntime().availableProcessors() * 8) .setHandler(new HttpHandler() { @Override diff --git a/src/com/wurrly/controllers/Users.java b/src/com/wurrly/controllers/Users.java index 30400e5..121e304 100644 --- a/src/com/wurrly/controllers/Users.java +++ b/src/com/wurrly/controllers/Users.java @@ -3,6 +3,7 @@ */ package com.wurrly.controllers; +import java.nio.ByteBuffer; import java.util.Collections; import java.util.Map; import java.util.Optional; @@ -16,7 +17,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; - +import javax.ws.rs.FormParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,7 +29,7 @@ import com.jsoniter.output.JsonStream; import com.typesafe.config.Config; import com.wurrly.models.User; -import com.wurrly.utilities.ServerRequest; +import com.wurrly.server.ServerRequest; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -42,6 +43,7 @@ @Singleton public class Users { + @Inject @Named("es.index.name") @@ -58,6 +60,38 @@ public Users() } + @GET + @Path("/{userId}/type") + @ApiOperation(value = "Find users by id with type", nickname = "user", httpMethod = "GET", response = User.class) + public Any userType(final ServerRequest serverRequest, @PathParam("userId") final Long userId, @QueryParam("context") Optional context, @QueryParam("type") User.UserType type) + { +// +// log.debug("esIndexName: " + esIndexName); +// log.debug("configuration: " + configuration); + +// log.debug("context: " + context); +// +// + return Any.wrap(new User(userId,type)); + + } + + @POST + @Path("/form") + @ApiOperation(value = "Find users by id with type", nickname = "user", httpMethod = "GET", response = User.class) + public Any userForm(final ServerRequest serverRequest, @PathParam("userId") final Long userId, @QueryParam("context") Optional context, @FormParam("type") User.UserType type, ByteBuffer testFile) + { +// +// log.debug("esIndexName: " + esIndexName); +// log.debug("configuration: " + configuration); + + log.debug("testFile: " + testFile); +// +// + return Any.wrap(new User(userId,type)); + + } + @GET @Path("/{userId}") @@ -80,7 +114,7 @@ public Any user(final ServerRequest serverRequest, @PathParam("userId") final Lo @Path("/") // @ApiImplicitParams({ @ApiImplicitParam(dataType = "com.wurrly.models.User", name = "user", paramType = "body", required = false, allowMultiple = false) }) @ApiOperation(value = "Find users by id", nickname = "user", httpMethod = "POST", response = JsonNode.class) - public User createUser(final ServerRequest serverRequest, @QueryParam("context") Optional context, final User user ) + public Any createUser(final ServerRequest serverRequest, @QueryParam("context") Optional context, final User user ) { // @@ -88,7 +122,7 @@ public User createUser(final ServerRequest serverRequest, @QueryParam("context" // log.debug("request: " + serverRequest); // log.debug("file: " + user); - return user; + return Any.wrap(user); diff --git a/src/com/wurrly/models/User.java b/src/com/wurrly/models/User.java index 1423b25..fa17626 100644 --- a/src/com/wurrly/models/User.java +++ b/src/com/wurrly/models/User.java @@ -3,10 +3,20 @@ */ package com.wurrly.models; +import com.jsoniter.annotation.JsonIgnore; + public class User { + public static enum UserType + { + GUEST,MEMBER,ADMIN + } + private Long id = 0l; + @JsonIgnore + private UserType type = UserType.GUEST; + public User() { @@ -16,6 +26,13 @@ public User(Long id) { this.id = id; } + + public User(Long id, UserType type) + { + this.id = id; + this.type = type; + } + /** * @return the id @@ -32,6 +49,22 @@ public void setId(Long id) { this.id = id; } + +// /** +// * @return the type +// */ +// public UserType getType() +// { +// return type; +// } + + /** + * @param type the type to set + */ + public void setType(UserType type) + { + this.type = type; + } diff --git a/src/com/wurrly/server/Extractors.java b/src/com/wurrly/server/Extractors.java new file mode 100644 index 0000000..187fec8 --- /dev/null +++ b/src/com/wurrly/server/Extractors.java @@ -0,0 +1,156 @@ +/** + * + */ +package com.wurrly.server; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Deque; +import java.util.Optional; + +import com.jsoniter.JsonIterator; +import com.jsoniter.any.Any; +import com.jsoniter.spi.TypeLiteral; + +import io.undertow.server.HttpServerExchange; +import io.undertow.server.handlers.form.FormDataParser; +import io.undertow.server.handlers.form.FormData.FormValue; + +/** + * @author jbauer + */ +public class Extractors +{ + public static class Optional + { + + public static final java.util.Optional jsonIterator(final HttpServerExchange exchange) + { + return java.util.Optional.ofNullable( JsonIterator.parse(exchange.getAttachment(ServerRequest.JSON_DATA).array())); + } + + public static final java.util.Optional typed(final HttpServerExchange exchange, final TypeLiteral type ) + { + return jsonIterator(exchange).map(i -> { + try + { + return i.read(type); + } catch (Exception e) + { + return null; + } + }); + } + + public static final java.util.Optional any(final HttpServerExchange exchange, final String name) + { + return java.util.Optional.ofNullable(exchange.getAttachment(ServerRequest.JSON_DATA)).map(t -> { + + return JsonIterator.deserialize(t.array()); + + }); + } + + public static final java.util.Optional integerValue(final HttpServerExchange exchange, final String name) + { + return string(exchange, name).map(Integer::parseInt); + } + + public static final java.util.Optional longValue(final HttpServerExchange exchange, final String name) + { + return string(exchange, name).map(Long::parseLong); + } + + public static final java.util.Optional booleanValue(final HttpServerExchange exchange, final String name) + { + return string(exchange, name).map(Boolean::parseBoolean); + } + + public static final > java.util.Optional enumValue(final HttpServerExchange exchange, final Class clazz, final String name) + { + return string(exchange, name).map(e -> Enum.valueOf(clazz, name)); + } + + public static final java.util.Optional string(final HttpServerExchange exchange, final String name) + { + return java.util.Optional.ofNullable(exchange.getQueryParameters().get(name)).map(Deque::getFirst); + } + + public static final 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(FormValue::getPath); + } + } + + public static final T typed(final HttpServerExchange exchange, final TypeLiteral type ) throws Exception + { + return jsonIterator(exchange).read(type); + } + + public static final Any any(final HttpServerExchange exchange, final String name) + { + try + { + return JsonIterator.parse( exchange.getAttachment(ServerRequest.JSON_DATA).array() ).readAny(); + } catch (IOException e) + { + return Any.wrapNull(); + } + } + + public static final JsonIterator jsonIterator(final HttpServerExchange exchange ) + { + return JsonIterator.parse(exchange.getAttachment(ServerRequest.JSON_DATA).array()); + } + + public static final Path filePath(final HttpServerExchange exchange, final String name) + { + return exchange.getAttachment(FormDataParser.FORM_DATA).get(name).getFirst().getPath(); + } + + public static final ByteBuffer fileBytes(final HttpServerExchange exchange, final String name) throws IOException + { + final Path filePath = filePath(exchange,name); + + try(final FileChannel fileChannel = FileChannel.open(filePath, StandardOpenOption.READ)) + { + final ByteBuffer buffer = ByteBuffer.allocate((int)fileChannel.size()); + + fileChannel.read(buffer); + + buffer.flip(); + + return buffer; + } + + } + + public static final String string(final HttpServerExchange exchange, final String name) + { + return exchange.getQueryParameters().get(name).getFirst(); + } + + public static final Long longValue(final HttpServerExchange exchange, final String name) + { + return Long.parseLong(string(exchange, name)); + } + + public static final Integer integerValue(final HttpServerExchange exchange, final String name) + { + return Integer.parseInt(string(exchange, name)); + } + + public static final Boolean booleanValue(final HttpServerExchange exchange, final String name) + { + return Boolean.parseBoolean(string(exchange, name)); + } + + public static final > E enumValue(final HttpServerExchange exchange, final String name, Class clazz) + { + return Enum.valueOf(clazz, string(exchange, name)); + } + +} diff --git a/src/com/wurrly/utilities/ServerRequest.java b/src/com/wurrly/server/ServerRequest.java similarity index 57% rename from src/com/wurrly/utilities/ServerRequest.java rename to src/com/wurrly/server/ServerRequest.java index 791c805..5eb6a92 100644 --- a/src/com/wurrly/utilities/ServerRequest.java +++ b/src/com/wurrly/server/ServerRequest.java @@ -1,7 +1,7 @@ /** * */ -package com.wurrly.utilities; +package com.wurrly.server; import java.io.File; import java.io.IOException; @@ -10,43 +10,47 @@ import java.net.URLDecoder; import java.nio.ByteBuffer; import java.util.Deque; +import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.Executor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.xnio.IoUtils; import org.xnio.channels.StreamSourceChannel; import com.jsoniter.JsonIterator; +import io.undertow.UndertowMessages; import io.undertow.connector.PooledByteBuffer; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.form.FormData; +import io.undertow.server.handlers.form.FormDataParser; import io.undertow.server.handlers.form.FormEncodedDataDefinition; import io.undertow.server.handlers.form.MultiPartParserDefinition; import io.undertow.util.AttachmentKey; +import io.undertow.util.FastConcurrentDirectDeque; import io.undertow.util.Headers; -import io.undertow.websockets.core.UTF8Output; +import io.undertow.util.MalformedMessageException; + +import java.util.stream.Collectors; public class ServerRequest { - private static Logger Logger = LoggerFactory.getLogger(ServerRequest.class.getCanonicalName()); - - public static final AttachmentKey REQUEST_JSON_BODY = AttachmentKey.create(JsonIterator.class); + private static Logger log = LoggerFactory.getLogger(ServerRequest.class.getCanonicalName()); - private static final String URL_ENCODED_FORM_TYPE = "x-www-form-urlencoded"; - private static final String FORM_DATA_TYPE = "form-data"; + public static final AttachmentKey JSON_DATA = AttachmentKey.create(ByteBuffer.class); + + private static final String OCTET_STREAM_TYPE = "octet-stream"; - private static final String JSON_TYPE = "application/json"; + private static final String APPLICATION_JSON = "application/json"; private static final String CHARSET = "UTF-8"; public final HttpServerExchange exchange; private final String path; - private FormData form; - private JsonIterator json; + private FormData form; private final String contentType; private final String method; @@ -71,15 +75,15 @@ public ServerRequest(HttpServerExchange exchange) throws IOException //Logger.debug("content tyoe: " + contentType); if (this.contentType != null) { - if (this.contentType.contains(URL_ENCODED_FORM_TYPE) || this.contentType.contains(OCTET_STREAM_TYPE)) + if (this.contentType.contains(FormEncodedDataDefinition.APPLICATION_X_WWW_FORM_URLENCODED) ) { this.parseEncodedForm(); } - else if (this.contentType.contains(FORM_DATA_TYPE)) + else if (this.contentType.contains(MultiPartParserDefinition.MULTIPART_FORM_DATA) || this.contentType.contains(OCTET_STREAM_TYPE)) { this.parseMultipartForm(); } - else if (this.contentType.contains(JSON_TYPE)) + else if (this.contentType.contains(APPLICATION_JSON)) { this.parseJson(); } @@ -141,27 +145,56 @@ public Map> getPathParameters() return exchange.getPathParameters(); } - private void parseEncodedForm() throws IOException - { - this.exchange.startBlocking(); - this.form = new FormEncodedDataDefinition().setDefaultEncoding(CHARSET).create(exchange).parseBlocking(); - - Logger.debug("Form " + form); - } + private void parseJson() throws IOException - { - // Logger.debug("parsing json"); - + { this.exchange.startBlocking(); if(this.exchange.getRequestContentLength() != -1) { +// ByteBuffer buffer = ByteBuffer.allocate((int) this.exchange.getRequestContentLength()); +// this.exchange.getRequestChannel().read(buffer); +// JsonIterator iterator = JsonIterator.parse(buffer.array()); +// this.exchange.putAttachment(JSON_DATA, iterator); + + try (PooledByteBuffer pooled = exchange.getConnection().getByteBufferPool().getArrayBackedPool().allocate()){ + ByteBuffer buf = pooled.getBuffer(); + + final StreamSourceChannel channel = this.exchange.getRequestChannel(); + + while (true) { + + buf.clear(); + + int c = channel.read(buf); + + + + if (c == -1) { + +// JsonIterator iterator = JsonIterator.parse(buf.array()); + int pos = buf.limit(); + + ByteBuffer buffer = ByteBuffer.allocate(pos); + + System.arraycopy(buf.array(), 0, buffer.array(), 0, pos); + + exchange.putAttachment(JSON_DATA, buffer); + break; + + } else if (c != 0) { + buf.limit(c); + } + } + } catch (MalformedMessageException e) { + throw new IOException(e); + } // try(PooledByteBuffer resource = this.exchange.getConnection().getByteBufferPool().allocate()) // { // final ByteBuffer buffer = resource.getBuffer(); -ByteBuffer buffer = ByteBuffer.allocate((int) this.exchange.getRequestContentLength()); + // final UTF8Output string = new UTF8Output(); // // final StreamSourceChannel channel = this.exchange.getRequestChannel(); @@ -184,10 +217,7 @@ private void parseJson() throws IOException // } while (r > 0); - this.exchange.getRequestChannel().read(buffer); - - JsonIterator iterator = JsonIterator.parse(buffer.array()); - this.exchange.putAttachment(REQUEST_JSON_BODY, iterator); + // } catch (IOException e) { // throw e; @@ -209,10 +239,10 @@ private void parseJson() throws IOException { String s = scanner.useDelimiter("\\A").next(); s = s.trim(); - JsonIterator iterator = JsonIterator.parse(s); - Logger.debug("iterator " + iterator); + // JsonIterator iterator = JsonIterator.parse(s); + // log.debug("iterator " + iterator); - this.exchange.putAttachment(REQUEST_JSON_BODY, iterator); + this.exchange.putAttachment(JSON_DATA, ByteBuffer.wrap(s.getBytes())); } } @@ -223,7 +253,7 @@ private void parseJson() throws IOException } } catch (IOException e) { - Logger.error("IOException: ", e); + log.error("IOException: ", e); } } @@ -240,11 +270,45 @@ private void parseMultipartForm() throws IOException { this.exchange.startBlocking(); - this.form = new MultiPartParserDefinition().setTempFileLocation(new File(TMP_DIR).toPath()).setDefaultEncoding(CHARSET).create(exchange).parseBlocking(); - - Logger.debug("Form " + form); + final FormDataParser formDataParser = new MultiPartParserDefinition() + .setTempFileLocation(new File(TMP_DIR).toPath()) + .setDefaultEncoding(CHARSET) + .create(this.exchange); - + log.debug(this.exchange+""); + + log.debug("boundary: " + Headers.extractQuotedValueFromHeader(this.contentType, "boundary")); + + if(formDataParser != null) + { + final FormData formData = formDataParser.parseBlocking(); + this.exchange.putAttachment(FormDataParser.FORM_DATA, formData); + extractFormParameters(formData); + } + } + + private void parseEncodedForm() throws IOException + { + + this.exchange.startBlocking(); + + final FormData formData = new FormEncodedDataDefinition().setDefaultEncoding(this.exchange.getRequestCharset()).create(exchange).parseBlocking(); + + this.exchange.putAttachment(FormDataParser.FORM_DATA, formData); + + extractFormParameters(formData); + } + + private void extractFormParameters(final FormData formData) + { + if (formData != null) { + for (String key : formData) + { + Deque formValues = formData.get(key); + Deque values = formValues.stream().filter(fv -> !fv.isFile()).map(FormData.FormValue::getValue).collect(java.util.stream.Collectors.toCollection(FastConcurrentDirectDeque::new)); + exchange.getQueryParameters().put(key, values); + } + } } public String queryString() diff --git a/src/com/wurrly/server/ServerResponse.java b/src/com/wurrly/server/ServerResponse.java new file mode 100644 index 0000000..139fea4 --- /dev/null +++ b/src/com/wurrly/server/ServerResponse.java @@ -0,0 +1,13 @@ +/** + * + */ +package com.wurrly.server; + +/** + * @author jbauer + * + */ +public class ServerResponse +{ + +} diff --git a/src/com/wurrly/tests/TestGenerator.java b/src/com/wurrly/tests/TestGenerator.java index 3bb9cd9..25267cf 100644 --- a/src/com/wurrly/tests/TestGenerator.java +++ b/src/com/wurrly/tests/TestGenerator.java @@ -30,8 +30,8 @@ import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.TypeSpec; import com.wurrly.controllers.Users; +import com.wurrly.server.ServerRequest; import com.wurrly.utilities.HandleGenerator; -import com.wurrly.utilities.ServerRequest; import io.undertow.server.HttpServerExchange; import io.undertow.util.HttpString; diff --git a/src/com/wurrly/tests/TestInvoker.java b/src/com/wurrly/tests/TestInvoker.java index 396f9e7..e903a73 100644 --- a/src/com/wurrly/tests/TestInvoker.java +++ b/src/com/wurrly/tests/TestInvoker.java @@ -18,7 +18,8 @@ import com.google.common.base.Throwables; import com.wurrly.controllers.Users; -import com.wurrly.utilities.ServerRequest; +import com.wurrly.server.ServerRequest; + import static java.lang.invoke.MethodHandles.lookup; import java.lang.invoke.CallSite; diff --git a/src/com/wurrly/utilities/HandleGenerator.java b/src/com/wurrly/utilities/HandleGenerator.java index f7d6ac1..09f6f0c 100644 --- a/src/com/wurrly/utilities/HandleGenerator.java +++ b/src/com/wurrly/utilities/HandleGenerator.java @@ -30,13 +30,19 @@ import org.slf4j.LoggerFactory; import com.google.common.base.Throwables; +import com.jsoniter.JsonIterator; import com.jsoniter.any.Any; import com.jsoniter.output.JsonStream; import com.wurrly.controllers.Users; import com.wurrly.models.User; +import com.wurrly.server.Extractors; +import com.wurrly.server.ServerRequest; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; +import io.undertow.server.handlers.form.FormData; +import io.undertow.server.handlers.form.FormDataParser; +import io.undertow.server.handlers.form.FormData.FormValue; import io.undertow.util.Headers; import io.undertow.util.HttpString; import io.undertow.util.Methods; @@ -165,57 +171,59 @@ public static HttpHandler generateHandler(final Users target, final Method targ final String[] parameterNames = new String[targetMethod.getParameterCount()]; final Type[] types = new Type[targetMethod.getParameterCount()]; - final BiFunction[] biFunctions = new BiFunction[targetMethod.getParameterCount()]; - - - - for( int i = 1; i < targetMethod.getParameterCount(); i++ ) - { - final Parameter p = targetMethod.getParameters()[i]; - parameterNames[i] = p.getName(); - types[i] = p.getParameterizedType(); - - Logger.debug("Type: " + types[i]); - - if( types[i].equals(Long.class) ) - { - Logger.debug("Long type"); - - biFunctions[i] = extractLong; - } - else if( types[i].equals(String.class) ) - { - Logger.debug("String type"); - - biFunctions[i] = extractString; - } - else if( types[i].equals(java.nio.file.Path.class) ) - { - Logger.debug("Path type"); - biFunctions[i] = extractFilePath; - } - else if( types[i].equals(Any.class) ) - { - Logger.debug("Any type"); - biFunctions[i] = extractAny; - } - else if( types[i].getTypeName().startsWith("java.util.Optional") ) - { - Type rawType = ((ParameterizedType) types[i] ); - - Logger.debug("Raw type: " + rawType); - - if( types[i].getTypeName().contains("java.lang.String") ) - { - biFunctions[i] = extractOptionalString; - } - - } - - } +// final BiFunction[] biFunctions = new BiFunction[targetMethod.getParameterCount()]; +// +// +// +// for( int i = 1; i < targetMethod.getParameterCount(); i++ ) +// { +// final Parameter p = targetMethod.getParameters()[i]; +// parameterNames[i] = p.getName(); +// types[i] = p.getParameterizedType(); +// +// Logger.debug("Type: " + types[i]); +// +// if( types[i].equals(Long.class) ) +// { +// Logger.debug("Long type"); +// +// biFunctions[i] = extractLong; +// } +// else if( types[i].equals(String.class) ) +// { +// Logger.debug("String type"); +// +// biFunctions[i] = extractString; +// } +// else if( types[i].equals(java.nio.file.Path.class) ) +// { +// Logger.debug("Path type"); +// biFunctions[i] = extractFilePath; +// } +// else if( types[i].equals(Any.class) ) +// { +// Logger.debug("Any type"); +// biFunctions[i] = extractAny; +// } +// else if( types[i].getTypeName().startsWith("java.util.Optional") ) +// { +// Type rawType = ((ParameterizedType) types[i] ); +// +// Logger.debug("Raw type: " + rawType); +// +// if( types[i].getTypeName().contains("java.lang.String") ) +// { +// biFunctions[i] = extractOptionalString; +// } +// +// } +// +// } // final Object[] args = new Object[targetMethod.getParameterCount()]; + final User tmpUser = new User(); + final HttpHandler mapper = new HttpHandler() { @Override @@ -241,12 +249,16 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception final ServerRequest request = new ServerRequest(exchange); -// final Long any = Long.parseLong(request.exchange.getQueryParameters().get("userId").getFirst()); + //final Long id = extractLong(exchange,"userId"); - final Optional context = Optional.ofNullable(request.exchange.getQueryParameters().get("context")).map(Deque::getFirst); + final Optional context = extractOptional(exchange,"context"); + //final User.UserType userType = extractEnum(exchange,"type",User.UserType.class); + + // final User user = extractJsonIterator(exchange,"user").read(User.class); + + //final Any json = target.userForm(request, id, context, userType, Extractors.fileBytes(exchange, "testFile")); + final Any json = target.createUser(request, context, Extractors.jsonIterator(exchange).read(User.class)); - final User json = target.createUser(request,context,request.exchange.getAttachment(ServerRequest.REQUEST_JSON_BODY).read(User.class)); - // json.whenComplete( ( u, e ) -> { // // if(e != null) @@ -258,7 +270,9 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception // else // { exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "application/json"); - exchange.getResponseSender().send(JsonStream.serialize(json)); + exchange.getResponseSender().send(JsonStream.serialize(json)); + + // } // // @@ -280,78 +294,117 @@ public void handleRequest(final HttpServerExchange exchange) throws Exception return null; } } + +// +// public final static BiFunction extractAny = (request,name) -> { +// +// try +// { +// return request.exchange.getAttachment(ServerRequest.JSON_DATA).readAny(); +// } catch (IOException e) +// { +// // TODO Auto-generated catch block +// return Any.wrap(false); +// } +// +// }; +// +// public static JsonIterator extractJsonIterator(final HttpServerExchange exchange, final String name) +// { +// return exchange.getAttachment(ServerRequest.JSON_DATA); +// } +// +// public static Any extractAny(final HttpServerExchange exchange, final String name) +// { +// try +// { +// return exchange.getAttachment(ServerRequest.JSON_DATA).readAny(); +// } catch (IOException e) +// { +// return Any.wrap(false); +// } +// } - public final static BiFunction extractLong = (request,name) -> { - - return Long.parseLong(request.exchange.getQueryParameters().get(name).getFirst()); - - }; + public static String extractString(final HttpServerExchange exchange, final String name) + { + return exchange.getQueryParameters().get(name).getFirst(); + } - public final static BiFunction extractAny = (request,name) -> { - - try - { - return request.exchange.getAttachment(ServerRequest.REQUEST_JSON_BODY).readAny(); - } catch (IOException e) - { - // TODO Auto-generated catch block - return Any.wrap(false); - } - - }; + public static Path extractFilePath(final HttpServerExchange exchange, final String name) + { + return exchange.getAttachment(FormDataParser.FORM_DATA).get(name).getFirst().getPath(); + } - public final static BiFunction extractFilePath = (request,name) -> { - - return request.files(name).getFirst().getPath(); - - }; + public static Long extractLong(final HttpServerExchange exchange, final String name) + { + return Long.parseLong(extractString(exchange,name)); + } - public final static BiFunction> extractOptionalString = (request,name) -> { - - return Optional.ofNullable(request.exchange.getQueryParameters().get(name)).map(Deque::getFirst); - - }; + public static Integer extractInteger(final HttpServerExchange exchange, final String name) + { + return Integer.parseInt(extractString(exchange,name)); + } - public final static BiFunction extractString = (request,name) -> { - - return request.exchange.getQueryParameters().get(name).getFirst(); - - }; + public static Boolean extractBoolean(final HttpServerExchange exchange, final String name) + { + return Boolean.parseBoolean(extractString(exchange,name)); + } - static Optional pathParamAsLong(HttpServerExchange exchange, String name) { - return baseParameter(exchange, name).map(Long::parseLong); - } - - static Optional pathParamAsInteger(HttpServerExchange exchange, String name) { - return baseParameter(exchange, name).map(Integer::parseInt); - } - - - static Optional baseParameter(HttpServerExchange exchange, String name) { - - return Optional.ofNullable(exchange.getQueryParameters().get(name)) - .map(Deque::getFirst); - } + public static > E extractEnum(final HttpServerExchange exchange, final String name, Class clazz) + { + return Enum.valueOf(clazz, extractString(exchange,name)); + } + + public static Optional extractOptional(final HttpServerExchange exchange, final String name) + { + return Optional.ofNullable(exchange.getQueryParameters().get(name)).map(Deque::getFirst); + } - private static interface RequestMapper extends Function + public static Optional extractOptionalFilePath(final HttpServerExchange exchange, final String name) { - T apply(HttpServerExchange exchange,String name); + return Optional.ofNullable(exchange.getAttachment(FormDataParser.FORM_DATA).get(name)).map(Deque::getFirst).map(FormValue::getPath); } - public static BiFunction stringParameterMapper = (HttpServerExchange exchange, String name) -> - { - return baseParameter(exchange,name).get(); - }; + public static Optional extractOptionalInteger(final HttpServerExchange exchange, final String name) + { + return extractOptional(exchange,name).map(Integer::parseInt); + } - public static BiFunction> longParameterMapper = (HttpServerExchange exchange, String name) -> - { - return baseParameter(exchange,name).map(Long::parseLong); - }; + public static Optional extractOptionalLong(final HttpServerExchange exchange, final String name) + { + return extractOptional(exchange,name).map(Long::parseLong); + } - public static BiFunction> optionalStringParameterMapper = (HttpServerExchange exchange, String name) -> - { - return baseParameter(exchange,name); - }; + public static Optional extractOptionalBoolean(final HttpServerExchange exchange, final String name) + { + return extractOptional(exchange,name).map(Boolean::parseBoolean); + } + + public static > Optional extractOptionalEnum(final HttpServerExchange exchange, final String name, Class clazz) + { + return extractOptional(exchange,name).map( e -> Enum.valueOf(clazz, name)); + } + + +// private static interface RequestMapper extends Function +// { +// T apply(HttpServerExchange exchange,String name); +// } + +// public static BiFunction stringParameterMapper = (HttpServerExchange exchange, String name) -> +// { +// return baseParameter(exchange,name).get(); +// }; +// +// public static BiFunction> longParameterMapper = (HttpServerExchange exchange, String name) -> +// { +// return baseParameter(exchange,name).map(Long::parseLong); +// }; +// +// public static BiFunction> optionalStringParameterMapper = (HttpServerExchange exchange, String name) -> +// { +// return baseParameter(exchange,name); +// }; // public static RequestMapper generateLongParameterMapper(String name) // {