collectedBeans = beanStream.collect(toList());
- assertThat(collectedBeans).hasSize(2);
-
- final HelloDto first = collectedBeans.get(0);
- assertThat(first.id).isEqualTo(42);
- assertThat(first.name).isEqualTo("rob");
-
- final HelloDto second = collectedBeans.get(1);
- assertThat(second.id).isEqualTo(45);
- assertThat(second.name).isEqualTo("fi");
- }
-
- @Test
- void post() {
- HelloDto dto = new HelloDto();
- dto.id = 42;
- dto.name = "rob was here";
-
- var res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:42 name:rob was here]");
- assertThat(res.statusCode()).isEqualTo(200);
-
- dto.id = 99;
- dto.name = "fi";
-
- res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:99 name:fi]");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-
-}
diff --git a/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/TestPair.java b/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/TestPair.java
deleted file mode 100644
index 4fbdf6c4..00000000
--- a/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/TestPair.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package io.avaje.jex.grizzly;
-
-import io.avaje.http.client.HttpClientContext;
-import io.avaje.http.client.HttpClientRequest;
-import io.avaje.http.client.JacksonBodyAdapter;
-import io.avaje.jex.Jex;
-
-import java.net.http.HttpClient;
-import java.util.Random;
-
-/**
- * Server and Client pair for a test.
- */
-public class TestPair {
-
- private final int port;
-
- private final Jex.Server server;
-
- private final HttpClientContext client;
-
- public TestPair(int port, Jex.Server server, HttpClientContext client) {
- this.port = port;
- this.server = server;
- this.client = client;
- }
-
- public void shutdown() {
- server.shutdown();
- }
-
- public HttpClientRequest request() {
- return client.request();
- }
-
- public int port() {
- return port;
- }
-
- public String url() {
- return client.url().build();
- }
-
- public static TestPair create(Jex app) {
- int port = 10000 + new Random().nextInt(1000);
- return create(app, port);
- }
-
- /**
- * Create a Server and Client pair for a given set of tests.
- */
- public static TestPair create(Jex app, int port) {
- var jexServer = app.port(port).start();
-
- var url = "http://localhost:" + port;
- var client = HttpClientContext.builder()
- .baseUrl(url)
- .bodyAdapter(new JacksonBodyAdapter())
- .version(HttpClient.Version.HTTP_1_1)
- .build();
-
- return new TestPair(port, jexServer, client);
- }
-}
diff --git a/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/VanillaMain.java b/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/VanillaMain.java
deleted file mode 100644
index 004d9091..00000000
--- a/avaje-jex-grizzly/src/test/java/io/avaje/jex/grizzly/VanillaMain.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.avaje.jex.grizzly;
-
-import org.glassfish.grizzly.http.server.*;
-
-import java.io.File;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-
-class VanillaMain {
-
- public static void main(String[] args) throws IOException, InterruptedException {
-
- File dir = new File(".");
- System.out.println("workingDirectory" + dir.getAbsolutePath());
-
- CLStaticHttpHandler clStaticHttpHandler = new CLStaticHttpHandler(VanillaMain.class.getClassLoader(), "/myres/");
- StaticHttpHandler staticHttpHandler = new StaticHttpHandler();
-
- final HttpServer httpServer = new HttpServerBuilder()
- .handler(clStaticHttpHandler, "cl")
- .handler(staticHttpHandler, "static")
- .handler(new MyHandler())
- .build();
-
- httpServer.start();
- Thread.currentThread().join();
- }
-
- static class MyHandler extends HttpHandler {
-
- @Override
- public void service(Request request, Response response) throws Exception {
- final SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
- final String date = format.format(new Date(System.currentTimeMillis()));
- response.setContentType("text/plain");
- response.setContentLength(date.length());
- response.getWriter().write(date);
- }
- }
-}
diff --git a/avaje-jex-grizzly/src/test/resources/myres/hello.txt b/avaje-jex-grizzly/src/test/resources/myres/hello.txt
deleted file mode 100644
index d6613f5f..00000000
--- a/avaje-jex-grizzly/src/test/resources/myres/hello.txt
+++ /dev/null
@@ -1 +0,0 @@
-Hello there
diff --git a/avaje-jex-htmx/pom.xml b/avaje-jex-htmx/pom.xml
new file mode 100644
index 00000000..8ee18a29
--- /dev/null
+++ b/avaje-jex-htmx/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+ io.avaje
+ avaje-jex-parent
+ 3.0
+
+
+ avaje-jex-htmx
+
+
+
+
+
+
+ io.avaje
+ avaje-htmx-api
+
+
+ io.avaje
+ avaje-jex
+
+
+
+
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandler.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandler.java
new file mode 100644
index 00000000..d892d4d0
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandler.java
@@ -0,0 +1,43 @@
+package io.avaje.jex.htmx;
+
+import static io.avaje.jex.htmx.HxHeaders.HX_REQUEST;
+import static io.avaje.jex.htmx.HxHeaders.HX_TARGET;
+import static io.avaje.jex.htmx.HxHeaders.HX_TRIGGER;
+import static io.avaje.jex.htmx.HxHeaders.HX_TRIGGER_NAME;
+
+import io.avaje.jex.http.Context;
+import io.avaje.jex.http.ExchangeHandler;
+
+final class DHxHandler implements ExchangeHandler {
+
+ private final ExchangeHandler delegate;
+ private final String target;
+ private final String trigger;
+ private final String triggerName;
+
+ DHxHandler(ExchangeHandler delegate, String target, String trigger, String triggerName) {
+ this.delegate = delegate;
+ this.target = target;
+ this.trigger = trigger;
+ this.triggerName = triggerName;
+ }
+
+ @Override
+ public void handle(Context ctx) throws Exception {
+ if (ctx.header(HX_REQUEST) != null && matched(ctx)) {
+ delegate.handle(ctx);
+ }
+ }
+
+ private boolean matched(Context ctx) {
+ if ((target != null && notMatched(ctx.header(HX_TARGET), target)) || (trigger != null && notMatched(ctx.header(HX_TRIGGER), trigger))) {
+ return false;
+ }
+ return triggerName == null || !notMatched(ctx.header(HX_TRIGGER_NAME), triggerName);
+ }
+
+ private boolean notMatched(String header, String matchValue) {
+ return header == null || !matchValue.equals(header);
+ }
+
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandlerBuilder.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandlerBuilder.java
new file mode 100644
index 00000000..eff808e9
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/DHxHandlerBuilder.java
@@ -0,0 +1,38 @@
+package io.avaje.jex.htmx;
+
+import io.avaje.jex.http.ExchangeHandler;
+
+final class DHxHandlerBuilder implements HxHandler.Builder {
+
+ private final ExchangeHandler delegate;
+ private String target;
+ private String trigger;
+ private String triggerName;
+
+ DHxHandlerBuilder(ExchangeHandler delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public DHxHandlerBuilder target(String target) {
+ this.target = target;
+ return this;
+ }
+
+ @Override
+ public DHxHandlerBuilder trigger(String trigger) {
+ this.trigger = trigger;
+ return this;
+ }
+
+ @Override
+ public DHxHandlerBuilder triggerName(String triggerName) {
+ this.triggerName = triggerName;
+ return this;
+ }
+
+ @Override
+ public ExchangeHandler build() {
+ return new DHxHandler(delegate, target, trigger, triggerName);
+ }
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHandler.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHandler.java
new file mode 100644
index 00000000..b684b0f3
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHandler.java
@@ -0,0 +1,46 @@
+package io.avaje.jex.htmx;
+
+import io.avaje.jex.http.ExchangeHandler;
+
+/**
+ * Wrap a Handler with filtering for Htmx specific headers.
+ *
+ * The underlying Handler will not be invoked unless the request
+ * is a Htmx request and matches the required attributes.
+ */
+public interface HxHandler {
+
+ /**
+ * Create a builder that wraps the underlying handler with Htmx
+ * specific attribute matching.
+ */
+ static Builder builder(ExchangeHandler delegate) {
+ return new DHxHandlerBuilder(delegate);
+ }
+
+ /**
+ * Build the Htmx request handler.
+ */
+ interface Builder {
+
+ /**
+ * Match on the given target.
+ */
+ Builder target(String target);
+
+ /**
+ * Match on the given trigger.
+ */
+ Builder trigger(String trigger);
+
+ /**
+ * Match on the given trigger name.
+ */
+ Builder triggerName(String triggerName);
+
+ /**
+ * Build and return the Handler.
+ */
+ ExchangeHandler build();
+ }
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHeaders.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHeaders.java
new file mode 100644
index 00000000..9d2a4da5
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxHeaders.java
@@ -0,0 +1,62 @@
+package io.avaje.jex.htmx;
+
+/**
+ * HTMX request headers.
+ *
+ * @see Request Headers Reference
+ */
+public interface HxHeaders {
+
+ /**
+ * Indicates that the request comes from an element that uses hx-boost.
+ *
+ * @see HX-Boosted
+ */
+ String HX_BOOSTED = "HX-Boosted";
+
+ /**
+ * The current URL of the browser
+ *
+ * @see HX-Current-URL
+ */
+ String HX_CURRENT_URL = "HX-Current-URL";
+
+ /**
+ * Indicates if the request is for history restoration after a miss in the local history cache.
+ *
+ * @see HX-History-Restore-Request
+ */
+ String HX_HISTORY_RESTORE_REQUEST = "HX-History-Restore-Request";
+
+ /**
+ * Contains the user response to a hx-prompt.
+ *
+ * @see HX-Prompt
+ */
+ String HX_PROMPT = "HX-Prompt";
+ /**
+ * Only present and {@code true} if the request is issued by htmx.
+ *
+ * @see HX-Request
+ */
+ String HX_REQUEST = "HX-Request";
+ /**
+ * The {@code id} of the target element if it exists.
+ *
+ * @see HX-Target
+ */
+ String HX_TARGET = "HX-Target";
+ /**
+ * The {@code name} of the triggered element if it exists
+ *
+ * @see HX-Trigger-Name
+ */
+ String HX_TRIGGER_NAME = "HX-Trigger-Name";
+ /**
+ * The {@code id} of the triggered element if it exists.
+ *
+ * @see HX-Trigger
+ */
+ String HX_TRIGGER = "HX-Trigger";
+
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxReq.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxReq.java
new file mode 100644
index 00000000..8b4cfb5e
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/HxReq.java
@@ -0,0 +1,49 @@
+package io.avaje.jex.htmx;
+
+import io.avaje.htmx.api.HtmxRequest;
+import io.avaje.jex.http.Context;
+
+/**
+ * Obtain the HtmxRequest for the given Jex Context.
+ */
+public final class HxReq {
+
+ /**
+ * Create given the server request.
+ */
+ public static HtmxRequest of(Context ctx) {
+ String header = ctx.header(HxHeaders.HX_REQUEST);
+ if (header == null) {
+ return HtmxRequest.EMPTY;
+ }
+
+ var builder = HtmxRequest.builder();
+ if (ctx.header(HxHeaders.HX_BOOSTED) != null) {
+ builder.boosted(true);
+ }
+ if (ctx.header(HxHeaders.HX_HISTORY_RESTORE_REQUEST) != null) {
+ builder.historyRestoreRequest(true);
+ }
+ var currentUrl = ctx.header(HxHeaders.HX_CURRENT_URL);
+ if (currentUrl != null) {
+ builder.currentUrl(currentUrl);
+ }
+ var prompt = ctx.header(HxHeaders.HX_PROMPT);
+ if (prompt != null) {
+ builder.promptResponse(prompt);
+ }
+ var target = ctx.header(HxHeaders.HX_TARGET);
+ if (target != null) {
+ builder.target(target);
+ }
+ var triggerName = ctx.header(HxHeaders.HX_TRIGGER_NAME);
+ if (triggerName != null) {
+ builder.triggerName(triggerName);
+ }
+ var trigger = ctx.header(HxHeaders.HX_TRIGGER);
+ if (trigger != null) {
+ builder.triggerId(trigger);
+ }
+ return builder.build();
+ }
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateContentCache.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateContentCache.java
new file mode 100644
index 00000000..5472bfa6
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateContentCache.java
@@ -0,0 +1,30 @@
+package io.avaje.jex.htmx;
+
+import io.avaje.jex.http.Context;
+
+/**
+ * Defines caching of template content.
+ */
+public interface TemplateContentCache {
+
+ /**
+ * Return the key given the request.
+ */
+ String key(Context req);
+
+ /**
+ * Return the key given the request with form parameters.
+ */
+ String key(Context req, Object formParams);
+
+ /**
+ * Return the content given the key.
+ */
+ String content(String key);
+
+ /**
+ * Put the content into the cache.
+ */
+ void contentPut(String key, String content);
+
+}
diff --git a/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateRender.java b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateRender.java
new file mode 100644
index 00000000..9dd8f9d2
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/io/avaje/jex/htmx/TemplateRender.java
@@ -0,0 +1,12 @@
+package io.avaje.jex.htmx;
+
+/**
+ * Template render API.
+ */
+public interface TemplateRender {
+
+ /**
+ * Render the given template view model to the server response.
+ */
+ String render(Object viewModel);
+}
diff --git a/avaje-jex-htmx/src/main/java/module-info.java b/avaje-jex-htmx/src/main/java/module-info.java
new file mode 100644
index 00000000..5dea08d2
--- /dev/null
+++ b/avaje-jex-htmx/src/main/java/module-info.java
@@ -0,0 +1,8 @@
+module io.avaje.jex.htmx {
+
+ requires transitive io.avaje.jex;
+ requires transitive io.avaje.htmx.api;
+ requires transitive jdk.httpserver;
+
+ exports io.avaje.jex.htmx;
+}
diff --git a/avaje-jex-jdk/pom.xml b/avaje-jex-jdk/pom.xml
deleted file mode 100644
index 04a8798b..00000000
--- a/avaje-jex-jdk/pom.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- avaje-jex-parent
- io.avaje
- 2.5
-
- 4.0.0
-
- avaje-jex-jdk
-
-
- 11
- 11
- false
-
-
-
-
-
- io.avaje
- avaje-jex
- 2.5
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.14.0
- test
-
-
-
-
-
-
diff --git a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/BaseHandler.java b/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/BaseHandler.java
deleted file mode 100644
index f9beef54..00000000
--- a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/BaseHandler.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package io.avaje.jex.jdk;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import io.avaje.jex.Context;
-import io.avaje.jex.Routing;
-import io.avaje.jex.http.NotFoundResponse;
-import io.avaje.jex.spi.SpiContext;
-import io.avaje.jex.spi.SpiRoutes;
-
-import java.util.Map;
-
-class BaseHandler implements HttpHandler {
-
- private final SpiRoutes routes;
- private final ServiceManager mgr;
-
- BaseHandler(SpiRoutes routes, ServiceManager mgr) {
- this.mgr = mgr;
- this.routes = routes;
- }
-
- void waitForIdle(long maxSeconds) {
- routes.waitForIdle(maxSeconds);
- }
-
- @Override
- public void handle(HttpExchange exchange) {
-
- final String uri = exchange.getRequestURI().getPath();
- final Routing.Type routeType = mgr.lookupRoutingType(exchange.getRequestMethod());
- final SpiRoutes.Entry route = routes.match(routeType, uri);
-
- if (route == null) {
- var ctx = new JdkContext(mgr, exchange, uri);
- routes.inc();
- try {
- processNoRoute(ctx, uri, routeType);
- routes.after(uri, ctx);
- } catch (Exception e) {
- handleException(ctx, e);
- } finally {
- routes.dec();
- }
- } else {
- route.inc();
- try {
- final Map params = route.pathParams(uri);
- JdkContext ctx = new JdkContext(mgr, exchange, route.matchPath(), params);
- try {
- processRoute(ctx, uri, route);
- routes.after(uri, ctx);
- } catch (Exception e) {
- handleException(ctx, e);
- }
- } finally {
- route.dec();
- }
- }
- }
-
- private void handleException(SpiContext ctx, Exception e) {
- mgr.handleException(ctx, e);
- }
-
- private void processRoute(JdkContext ctx, String uri, SpiRoutes.Entry route) {
- routes.before(uri, ctx);
- ctx.setMode(null);
- route.handle(ctx);
- }
-
- private void processNoRoute(JdkContext ctx, String uri, Routing.Type routeType) {
- routes.before(uri, ctx);
- if (routeType == Routing.Type.HEAD && hasGetHandler(uri)) {
- processHead(ctx);
- return;
- }
-// if (routeType == Routing.Type.GET || routeType == Routing.Type.HEAD) {
-// // check if handled by static resource
-// // check if handled by singlePageHandler
-// }
- throw new NotFoundResponse("uri: " + uri);
- }
-
- private void processHead(Context ctx) {
- ctx.status(200);
- }
-
- private boolean hasGetHandler(String uri) {
- return routes.match(Routing.Type.GET, uri) != null;
- }
-
-}
diff --git a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/JdkServerStart.java b/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/JdkServerStart.java
deleted file mode 100644
index 47e7d8a5..00000000
--- a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/JdkServerStart.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package io.avaje.jex.jdk;
-
-import com.sun.net.httpserver.HttpServer;
-import io.avaje.applog.AppLog;
-import io.avaje.jex.AppLifecycle;
-import io.avaje.jex.Jex;
-import io.avaje.jex.spi.SpiRoutes;
-import io.avaje.jex.spi.SpiServiceManager;
-import io.avaje.jex.spi.SpiStartServer;
-
-import java.io.IOException;
-import java.lang.System.Logger.Level;
-import java.net.InetSocketAddress;
-import java.util.concurrent.Executor;
-
-public class JdkServerStart implements SpiStartServer {
-
- private static final System.Logger log = AppLog.getLogger("io.avaje.jex");
-
- @Override
- public Jex.Server start(Jex jex, SpiRoutes routes, SpiServiceManager serviceManager) {
- final ServiceManager manager = new ServiceManager(serviceManager, "http", "");
- BaseHandler handler = new BaseHandler(routes, manager);
- try {
- final HttpServer server = HttpServer.create();
- server.createContext("/", handler);
- final Executor executor = jex.attribute(Executor.class);
- if (executor != null) {
- server.setExecutor(executor);
- }
- int port = jex.config().port();
- server.bind(new InetSocketAddress(port), 0);
- server.start();
- jex.lifecycle().status(AppLifecycle.Status.STARTED);
- String jexVersion = Jex.class.getPackage().getImplementationVersion();
- log.log(Level.INFO, "started server on port {0,number,#} version {1}", port, jexVersion);
- return new JdkJexServer(server, jex.lifecycle(), handler);
-
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/ServiceManager.java b/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/ServiceManager.java
deleted file mode 100644
index 59df313c..00000000
--- a/avaje-jex-jdk/src/main/java/io/avaje/jex/jdk/ServiceManager.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.spi.ProxyServiceManager;
-import io.avaje.jex.spi.SpiServiceManager;
-
-import java.io.OutputStream;
-
-class ServiceManager extends ProxyServiceManager {
-
- private final String scheme;
- private final String contextPath;
- private final long outputBufferMax = 1024;
- private final int outputBufferInitial = 256;
-
- ServiceManager(SpiServiceManager delegate, String scheme, String contextPath) {
- super(delegate);
- this.scheme = scheme;
- this.contextPath = contextPath;
- }
-
- OutputStream createOutputStream(JdkContext jdkContext) {
- return new BufferedOutStream(jdkContext, outputBufferMax, outputBufferInitial);
- }
-
- String scheme() {
- return scheme;
- }
-
- public String url(JdkContext jdkContext) {
- return scheme+"://";
- }
-
- public String contextPath() {
- return contextPath;
- }
-}
diff --git a/avaje-jex-jdk/src/main/java/module-info.java b/avaje-jex-jdk/src/main/java/module-info.java
deleted file mode 100644
index a30fd880..00000000
--- a/avaje-jex-jdk/src/main/java/module-info.java
+++ /dev/null
@@ -1,11 +0,0 @@
-import io.avaje.jex.jdk.JdkServerStart;
-import io.avaje.jex.spi.SpiStartServer;
-
-module io.avaje.jex.jdk {
-
- requires transitive io.avaje.jex;
- requires transitive java.net.http;
- requires transitive jdk.httpserver;
-
- provides SpiStartServer with JdkServerStart;
-}
diff --git a/avaje-jex-jdk/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer b/avaje-jex-jdk/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer
deleted file mode 100644
index 79199ebe..00000000
--- a/avaje-jex-jdk/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer
+++ /dev/null
@@ -1 +0,0 @@
-io.avaje.jex.jdk.JdkServerStart
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextAttributeTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextAttributeTest.java
deleted file mode 100644
index 116ff93f..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextAttributeTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextAttributeTest {
-
- static final UUID uuid = UUID.randomUUID();
-
- static TestPair pair = init();
-
- static TestPair attrPair;
- static UUID attrUuid;
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .before(ctx -> {
- ctx.attribute("oneUuid", uuid).attribute(TestPair.class.getName(), pair);
- })
- .get("/", ctx -> {
- attrUuid = ctx.attribute("oneUuid");
- attrPair = ctx.attribute(TestPair.class.getName());
-
- assert attrUuid == uuid;
- assert attrPair == pair;
-
-// ctx.attributeMap() is not supported
-// final Map attrMap = ctx.attributeMap();
-// final Object mapUuid = attrMap.get("oneUuid");
-// assert mapUuid == uuid;
-//
-// final Object mapPair = attrMap.get(TestPair.class.getName());
-// assert mapPair == pair;
- ctx.text("all-good");
- })
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("all-good");
-
- assertThat(attrPair).isSameAs(pair);
- assertThat(attrUuid).isSameAs(uuid);
- }
-
-
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextFormParamTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextFormParamTest.java
deleted file mode 100644
index 6ca5e2c0..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextFormParamTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextFormParamTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .post("/", ctx -> ctx.text("map:" +ctx.formParamMap()))
- .post("/formParams/{key}", ctx -> ctx.text("formParams:" + ctx.formParams(ctx.pathParam("key"))))
- .post("/formParam/{key}", ctx -> ctx.text("formParam:" + ctx.formParam(ctx.pathParam("key"))))
- .post("/formParamWithDefault/{key}", ctx -> ctx.text("formParam:" + ctx.formParam(ctx.pathParam("key"), "foo")))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void formParamMap() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("map:{one=[ao, bo], two=[z]}");
- }
-
-
- @Test
- void formParams_one() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParams").path("one")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParams:[ao, bo]");
- }
-
- @Test
- void formParams_two() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParams").path("two")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParams:[z]");
- }
-
-
- @Test
- void formParam_null() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParam").path("doesNotExist")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParam:null");
- }
-
- @Test
- void formParam_first() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParam").path("one")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParam:ao");
- }
-
- @Test
- void formParam_default() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParamWithDefault").path("doesNotExist")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParam:foo");
- }
-
- @Test
- void formParam_default_first() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParamWithDefault").path("one")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParam:ao");
- }
-
- @Test
- void formParam_default_only() {
- HttpResponse res = pair.request()
- .formParam("one", "ao")
- .formParam("one", "bo")
- .formParam("two", "z")
- .path("formParamWithDefault").path("two")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("formParam:z");
- }
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextLengthTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextLengthTest.java
deleted file mode 100644
index f817711a..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/ContextLengthTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextLengthTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .post("/", ctx -> ctx.text("contentLength:" + ctx.contentLength() + " type:" + ctx.contentType()))
- .get("/url", ctx -> ctx.text("url:" + ctx.url()))
- .get("/fullUrl", ctx -> ctx.text("fullUrl:" + ctx.fullUrl()))
- .get("/contextPath", ctx -> ctx.text("contextPath:" + ctx.contextPath()))
- .get("/userAgent", ctx -> ctx.text("userAgent:" + ctx.userAgent()))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void when_noReqContentType() {
- HttpResponse res = pair.request().body("MyBodyContent")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contentLength:13 type:null");
- }
-
- @Test
- void requestContentLengthAndType_notReqContentType() {
- HttpResponse res = pair.request()
- .formParam("a", "my-a-val")
- .formParam("b", "my-b-val")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contentLength:21 type:application/x-www-form-urlencoded");
- }
-
- @Test
- void url() {
- HttpResponse res = pair.request()
- .path("url")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("url:http://localhost:" + pair.port() + "/url");
- }
-
- @Test
- void fullUrl_no_queryString() {
- HttpResponse res = pair.request()
- .path("fullUrl")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("fullUrl:http://localhost:" + pair.port() + "/fullUrl");
- }
-
- @Test
- void fullUrl_queryString() {
- HttpResponse res = pair.request()
- .path("fullUrl")
- .queryParam("a", "av")
- .queryParam("b", "bv")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("fullUrl:http://localhost:" + pair.port() + "/fullUrl?a=av&b=bv");
- }
-
- @Test
- void contextPath() {
- HttpResponse res = pair.request()
- .path("contextPath")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contextPath:");
- }
-
- @Test
- void userAgent() {
- HttpResponse res = pair.request()
- .path("userAgent")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).contains("userAgent:Java-http-client");
- }
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/FilterTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/FilterTest.java
deleted file mode 100644
index 9280e929..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/FilterTest.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpHeaders;
-import java.net.http.HttpResponse;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class FilterTest {
-
- static TestPair pair = init();
- static AtomicReference afterAll = new AtomicReference<>();
- static AtomicReference afterTwo = new AtomicReference<>();
-
- static TestPair init() {
- final Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.text("roo"))
- .get("/one", ctx -> ctx.text("one"))
- .get("/two", ctx -> ctx.text("two"))
- .get("/two/{id}", ctx -> ctx.text("two-id"))
- .before(ctx -> {
- ctx.header("before-all", "set");
- })
- .before("/two/*", ctx -> ctx.header("before-two", "set"))
- .after(ctx -> {
- afterAll.set("set");
- })
- .after("/two/*", ctx -> afterTwo.set("set"))
- .get("/dummy", ctx -> ctx.text("dummy"))
- );
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- void clearAfter() {
- afterAll.set(null);
- afterTwo.set(null);
- }
-
- @Test
- void get() {
- clearAfter();
- HttpResponse res = pair.request().GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
-
- clearAfter();
- res = pair.request().path("one").GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
-
- clearAfter();
- res = pair.request().path("two").GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
- }
-
-
- @Test
- void get_two_expect_extraFilters() {
- clearAfter();
- HttpResponse res = pair.request().path("two/42").GET().asString();
-
- final HttpHeaders headers = res.headers();
- assertHasBeforeAfterAll(res);
- assertThat(headers.firstValue("before-two")).get().isEqualTo("set");
- assertThat(afterTwo.get()).isEqualTo("set");
- }
-
- private void assertNoBeforeAfterTwo(HttpResponse res) {
- assertThat(res.headers().firstValue("before-two")).isEmpty();
- assertThat(afterTwo.get()).isNull();
- }
-
- private void assertHasBeforeAfterAll(HttpResponse res) {
- assertThat(res.headers().firstValue("before-all")).get().isEqualTo("set");
- assertThat(afterAll.get()).isEqualTo("set");
- }
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/JsonTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/JsonTest.java
deleted file mode 100644
index 8a61e434..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/JsonTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpHeaders;
-import java.net.http.HttpResponse;
-import java.util.List;
-import java.util.stream.Stream;
-
-import static java.util.Arrays.asList;
-import static java.util.stream.Collectors.toList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-class JsonTest {
-
- static List HELLO_BEANS = asList(HelloDto.rob(), HelloDto.fi());
-
- static AutoCloseIterator ITERATOR = createBeanIterator();
-
- private static AutoCloseIterator createBeanIterator() {
- return new AutoCloseIterator<>(HELLO_BEANS.iterator());
- }
-
- static TestPair pair = init();
-
- static TestPair init() {
- Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.json(HelloDto.rob()).status(200))
- .get("/iterate", ctx -> ctx.jsonStream(ITERATOR))
- .get("/stream", ctx -> ctx.jsonStream(HELLO_BEANS.stream()))
- .post("/", ctx -> ctx.text("bean[" + ctx.bodyAsClass(HelloDto.class) + "]")));
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
-
- var bean = pair.request()
- .GET()
- .bean(HelloDto.class);
-
- assertThat(bean.id).isEqualTo(42);
- assertThat(bean.name).isEqualTo("rob");
-
- final HttpResponse hres = pair.request()
- .GET().asString();
-
- final HttpHeaders headers = hres.headers();
- assertThat(headers.firstValue("Content-Type").get()).isEqualTo("application/json");
- }
-
- @Test
- void stream_viaIterator() {
- final Stream beanStream = pair.request()
- .path("iterate")
- .GET()
- .stream(HelloDto.class);
-
- // expect client gets the expected stream of beans
- assertCollectedStream(beanStream);
- // assert AutoCloseable iterator on the server-side was closed
- assertThat(ITERATOR.isClosed()).isTrue();
- }
-
- @Test
- void stream() {
- final Stream beanStream = pair.request()
- .path("stream")
- .GET()
- .stream(HelloDto.class);
-
- assertCollectedStream(beanStream);
- }
-
- private void assertCollectedStream(Stream beanStream) {
- final List collectedBeans = beanStream.collect(toList());
- assertThat(collectedBeans).hasSize(2);
-
- final HelloDto first = collectedBeans.get(0);
- assertThat(first.id).isEqualTo(42);
- assertThat(first.name).isEqualTo("rob");
-
- final HelloDto second = collectedBeans.get(1);
- assertThat(second.id).isEqualTo(45);
- assertThat(second.name).isEqualTo("fi");
- }
-
- @Test
- void post() {
- HelloDto dto = new HelloDto();
- dto.id = 42;
- dto.name = "rob was here";
-
- var res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:42 name:rob was here]");
- assertThat(res.statusCode()).isEqualTo(200);
-
- dto.id = 99;
- dto.name = "fi";
-
- res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:99 name:fi]");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/QueryParamTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/QueryParamTest.java
deleted file mode 100644
index 64e7ed13..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/QueryParamTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-import java.util.Map;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class QueryParamTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.text("hello"))
- .get("/one/{id}", ctx -> ctx.text("one-" + ctx.pathParam("id") + "|match:" + ctx.matchedPath()))
- .get("/one/{id}/{b}", ctx -> ctx.text("path:" + ctx.pathParamMap() + "|query:" + ctx.queryParam("z") + "|match:" + ctx.matchedPath()))
- .get("/queryParamMap", ctx -> ctx.text("qpm: "+ctx.queryParamMap()))
- .get("/queryParams", ctx -> ctx.text("qps: "+ctx.queryParams("a")))
- .get("/queryString", ctx -> ctx.text("qs: "+ctx.queryString()))
- .get("/scheme", ctx -> ctx.text("scheme: "+ctx.scheme()))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("hello");
- }
-
- @Test
- void getOne_path() {
- var res = pair.request()
- .path("one").path("foo").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("one-foo|match:/one/{id}");
-
- res = pair.request()
- .path("one").path("bar").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("one-bar|match:/one/{id}");
- }
-
- @Test
- void getOne_path_path() {
- var res = pair.request()
- .path("one").path("foo").path("bar")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("path:{id=foo, b=bar}|query:null|match:/one/{id}/{b}");
-
- res = pair.request()
- .path("one").path("fo").path("ba").queryParam("z", "42")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("path:{id=fo, b=ba}|query:42|match:/one/{id}/{b}");
- }
-
- @Test
- void queryParamMap_when_empty() {
- HttpResponse res = pair.request().path("queryParamMap").GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qpm: {}");
- }
-
- @Test
- void queryParamMap_keyWithMultiValues_expect_firstValueInMap() {
- HttpResponse res = pair.request().path("queryParamMap")
- .queryParam("a","AVal0")
- .queryParam("a","AVal1")
- .queryParam("b", "BVal")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qpm: {a=AVal0, b=BVal}");
- }
-
- @Test
- void queryParamMap_basic() {
- HttpResponse res = pair.request().path("queryParamMap")
- .queryParam("a","AVal")
- .queryParam("b", "BVal")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qpm: {a=AVal, b=BVal}");
- }
-
- @Test
- void queryParams_basic() {
- HttpResponse res = pair.request().path("queryParams")
- .queryParam("a","one")
- .queryParam("a", "two")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qps: [one, two]");
- }
-
- @Test
- void queryParams_when_null_expect_emptyList() {
- HttpResponse res = pair.request().path("queryParams")
- .queryParam("b","one")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qps: []");
- }
-
- @Test
- void queryString_when_null() {
- HttpResponse res = pair.request().path("queryString")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qs: null");
- }
-
- @Test
- void queryString_when_set() {
- HttpResponse res = pair.request().path("queryString")
- .queryParam("foo","f1")
- .queryParam("bar","b1")
- .queryParam("bar","b2")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("qs: foo=f1&bar=b1&bar=b2");
- }
-
- @Test
- void scheme() {
- HttpResponse res = pair.request().path("scheme")
- .queryParam("foo","f1")
- .GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("scheme: http");
- }
-
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/RedirectTest.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/RedirectTest.java
deleted file mode 100644
index 418b21be..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/RedirectTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class RedirectTest {
-
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .before("/other/*", ctx -> ctx.redirect("/two?from=filter"))
- .get("/one", ctx -> ctx.text("one"))
- .get("/two", ctx -> ctx.text("two"))
- .get("/redirect/me", ctx -> ctx.redirect("/one?from=handler"))
- .get("/other/me", ctx -> ctx.text("never hit"))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void redirect_via_handler() {
- HttpResponse res = pair.request().path("redirect/me").GET().asString();
- assertThat(res.body()).isEqualTo("one");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-
- @Test
- void redirect_via_beforeHandler() {
- HttpResponse res = pair.request().path("other/me").GET().asString();
- assertThat(res.body()).isEqualTo("two");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-}
diff --git a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/TestPair.java b/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/TestPair.java
deleted file mode 100644
index 9bac68c2..00000000
--- a/avaje-jex-jdk/src/test/java/io/avaje/jex/jdk/TestPair.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package io.avaje.jex.jdk;
-
-import io.avaje.http.client.HttpClientContext;
-import io.avaje.http.client.HttpClientRequest;
-import io.avaje.http.client.JacksonBodyAdapter;
-import io.avaje.jex.Jex;
-
-import java.time.Duration;
-import java.util.Random;
-
-/**
- * Server and Client pair for a test.
- */
-public class TestPair {
-
- private final int port;
-
- private final Jex.Server server;
-
- private final HttpClientContext client;
-
- public TestPair(int port, Jex.Server server, HttpClientContext client) {
- this.port = port;
- this.server = server;
- this.client = client;
- }
-
- public void shutdown() {
- server.shutdown();
- }
-
- public HttpClientRequest request() {
- return client.request();
- }
-
- public int port() {
- return port;
- }
-
- public String url() {
- return client.url().build();
- }
-
- /**
- * Create a Server and Client pair for a given set of tests.
- */
- public static TestPair create(Jex app) {
- int port = 10000 + new Random().nextInt(1000);
- return create(app, port);
- }
-
- public static TestPair create(Jex app, int port) {
-
- var jexServer = app.port(port).start();
-
- var url = "http://localhost:" + port;
- var client = HttpClientContext.builder()
- .baseUrl(url)
- .bodyAdapter(new JacksonBodyAdapter())
- .requestTimeout(Duration.ofMinutes(2))
- .build();
-
- return new TestPair(port, jexServer, client);
- }
-}
diff --git a/avaje-jex-jdk/src/test/resources/logback-test.xml b/avaje-jex-jdk/src/test/resources/logback-test.xml
deleted file mode 100644
index 5e5a132a..00000000
--- a/avaje-jex-jdk/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- TRACE
-
-
- %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/avaje-jex-jetty/pom.xml b/avaje-jex-jetty/pom.xml
deleted file mode 100644
index bd9cd88f..00000000
--- a/avaje-jex-jetty/pom.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
- avaje-jex-parent
- io.avaje
- 2.5
-
- 4.0.0
-
- avaje-jex-jetty
-
-
- 11
- 11
- 11.0.13
- false
-
-
-
-
- io.avaje
- avaje-jex
- 2.5
-
-
-
- org.eclipse.jetty
- jetty-server
- ${jetty.version}
-
-
-
- com.mashape.unirest
- unirest-java
- 1.4.9
- test
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.14.0
- test
-
-
-
-
-
-
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java
deleted file mode 100644
index c986ffbe..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ContextUtil.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.avaje.jex.jetty;
-
-import jakarta.servlet.ServletInputStream;
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.io.*;
-
-class ContextUtil {
-
- private static final int DEFAULT_BUFFER_SIZE = 8 * 1024;
-
- private static final int BUFFER_MAX = 65536;
-
- static byte[] readBody(HttpServletRequest req) {
- try {
- final ServletInputStream inputStream = req.getInputStream();
-
- int bufferSize = inputStream.available();
- if (bufferSize < DEFAULT_BUFFER_SIZE) {
- bufferSize = DEFAULT_BUFFER_SIZE;
- } else if (bufferSize > BUFFER_MAX) {
- bufferSize = BUFFER_MAX;
- }
-
- ByteArrayOutputStream os = new ByteArrayOutputStream(bufferSize);
- copy(inputStream, os, bufferSize);
- return os.toByteArray();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- static void copy(InputStream in, OutputStream out, int bufferSize) throws IOException {
- byte[] buffer = new byte[bufferSize];
- int len;
- while ((len = in.read(buffer, 0, bufferSize)) > 0) {
- out.write(buffer, 0, len);
- }
- }
-
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyBuilder.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyBuilder.java
deleted file mode 100644
index 99d59652..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.JexConfig;
-import io.avaje.jex.Jex;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.jetty.util.thread.ThreadPool;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.lang.reflect.Constructor;
-
-/**
- * Build the Jetty Server.
- */
-class JettyBuilder {
-
- private static final Logger log = LoggerFactory.getLogger(JettyBuilder.class);
-
- private final JexConfig jexConfig;
- private final JettyServerConfig jettyConfig;
-
- JettyBuilder(Jex jex, JettyServerConfig jettyConfig) {
- this.jexConfig = jex.config();
- this.jettyConfig = jettyConfig;
- }
-
- Server build() {
- Server jetty = new Server(pool());
- ServerConnector connector = new ServerConnector(jetty);
- connector.setPort(jexConfig.port());
- if (jexConfig.host() != null ) {
- connector.setHost(jexConfig.host());
- }
- jetty.setConnectors(new Connector[]{connector});
- return jetty;
- }
-
- private ThreadPool pool() {
- if (jexConfig.virtualThreads()) {
- return virtualThreadBasePool();
- } else {
- return jettyConfig.maxThreads() == 0 ? new QueuedThreadPool() : new QueuedThreadPool(jettyConfig.maxThreads());
- }
- }
-
- private ThreadPool virtualThreadBasePool() {
- try {
- final Class> aClass = Class.forName("io.avaje.jex.jetty.threadpool.VirtualThreadPool");
- final Constructor> constructor = aClass.getConstructor();
- return (ThreadPool) constructor.newInstance();
- } catch (Exception e) {
- throw new IllegalStateException("Failed to start Loom threadPool", e);
- }
- }
-
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
deleted file mode 100644
index 7253c3a7..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyJexServer.java
+++ /dev/null
@@ -1,169 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.*;
-import io.avaje.jex.spi.SpiRoutes;
-import io.avaje.jex.spi.SpiServiceManager;
-import jakarta.servlet.MultipartConfigElement;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.util.Uptime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-
-class JettyJexServer implements Jex.Server {
-
- private static final Logger log = LoggerFactory.getLogger(Jex.class);
-
- private final Jex jex;
- private final SpiRoutes routes;
- private final ServiceManager serviceManager;
- private final JettyServerConfig config;
- private final AppLifecycle lifecycle;
- private final long startTime;
- private final JexConfig jexConfig;
- private Server server;
-
- JettyJexServer(Jex jex, SpiRoutes routes, SpiServiceManager serviceManager) {
- this.startTime = System.currentTimeMillis();
- this.jex = jex;
- this.jexConfig = jex.config();
- this.lifecycle = jex.lifecycle();
- this.routes = routes;
- this.serviceManager = new ServiceManager(serviceManager, initMultiPart());
- this.config = initConfig(jex.serverConfig());
- }
-
- private JettyServerConfig initConfig(ServerConfig config) {
- return config == null ? new JettyServerConfig() : (JettyServerConfig) config;
- }
-
- MultipartUtil initMultiPart() {
- return new MultipartUtil(initMultipartConfigElement(jexConfig.multipartConfig()));
- }
-
- MultipartConfigElement initMultipartConfigElement(UploadConfig uploadConfig) {
- if (uploadConfig == null) {
- final int fileThreshold = jexConfig.multipartFileThreshold();
- return new MultipartConfigElement(System.getProperty("java.io.tmpdir"), -1, -1, fileThreshold);
- }
- return new MultipartConfigElement(uploadConfig.location(), uploadConfig.maxFileSize(), uploadConfig.maxRequestSize(), uploadConfig.fileSizeThreshold());
- }
-
- @Override
- public void onShutdown(Runnable onShutdown) {
- lifecycle.onShutdown(onShutdown, Integer.MAX_VALUE);
- }
-
- @Override
- public void restart() {
- try {
- server.start();
- logOnStart(server);
- lifecycle.status(AppLifecycle.Status.STARTED);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public void shutdown() {
- try {
- log.trace("starting shutdown");
- lifecycle.status(AppLifecycle.Status.STOPPING);
- routes.waitForIdle(30);
- server.stop();
- log.trace("server http listeners stopped");
- lifecycle.status(AppLifecycle.Status.STOPPED);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public int port() {
- return server.getURI().getPort();
- }
-
- protected Jex.Server start() {
- try {
- createServer();
- server.start();
- logOnStart(server);
- lifecycle.registerShutdownHook(this::shutdown);
- lifecycle.status(AppLifecycle.Status.STARTED);
- return this;
- } catch (Exception e) {
- throw new IllegalStateException("Error starting server", e);
- }
- }
-
- protected void createServer() {
- server = initServer();
- server.setHandler(initJettyHandler());
- if (server.getStopAtShutdown()) {
- // do not use Jetty ShutdownHook, use the AppLifecycle one instead
- server.setStopAtShutdown(false);
- }
- config.server(server);
- config.postConfigure();
- }
-
- protected Server initServer() {
- Server server = config.server();
- if (server != null) {
- return server;
- }
- return new JettyBuilder(jex, config).build();
- }
-
- protected Handler initJettyHandler() {
- var baseHandler = new JexHandler(jex, routes, serviceManager, initStaticHandler());
- if (!config.sessions()) {
- return baseHandler;
- }
- var sessionHandler = initSessionHandler();
- sessionHandler.setHandler(baseHandler);
- return sessionHandler;
- }
-
- protected SessionHandler initSessionHandler() {
- SessionHandler sh = config.sessionHandler();
- return sh == null ? defaultSessionHandler() : sh;
- }
-
- protected SessionHandler defaultSessionHandler() {
- SessionHandler sh = new SessionHandler();
- sh.setHttpOnly(true);
- return sh;
- }
-
- protected StaticHandler initStaticHandler() {
- final List fileSources = jex.staticFiles().getSources();
- if (fileSources == null || fileSources.isEmpty()) {
- return null;
- }
- StaticHandlerFactory factory = new StaticHandlerFactory();
- return factory.build(server, jex, fileSources);
- }
-
- private void logOnStart(org.eclipse.jetty.server.Server server) {
- long startup = System.currentTimeMillis() - startTime;
- for (Connector c : server.getConnectors()) {
- String virtualThreads = jexConfig.virtualThreads() ? "with virtualThreads" : "";
- if (c instanceof ServerConnector) {
- ServerConnector sc = (ServerConnector) c;
- String host = (sc.getHost() == null) ? "0.0.0.0" : sc.getHost();
- log.info("Listening with {} {}:{} in {}ms @{}ms {}", sc.getProtocols(), host, sc.getLocalPort(), startup, Uptime.getUptime(), virtualThreads);
- } else {
- log.info("bind to {} in {}ms @{}ms {}", c, startup, Uptime.getUptime(), virtualThreads);
- }
- }
- }
-
-
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
deleted file mode 100644
index f8c41a17..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyServerConfig.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.ServerConfig;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.session.SessionHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public class JettyServerConfig implements ServerConfig {
-
- private boolean sessions = true;
- private boolean security = true;
-
- /**
- * Set maxThreads when using default QueuedThreadPool. Defaults to 200.
- */
- private int maxThreads;
- private SessionHandler sessionHandler;
- private Handler contextHandler;
- private Server server;
- private final List> configureCallback = new ArrayList<>();
-
- public boolean sessions() {
- return sessions;
- }
-
- public JettyServerConfig sessions(boolean sessions) {
- this.sessions = sessions;
- return this;
- }
-
- public boolean security() {
- return security;
- }
-
- public JettyServerConfig security(boolean security) {
- this.security = security;
- return this;
- }
-
- public int maxThreads() {
- return maxThreads;
- }
-
- public JettyServerConfig maxThreads(int maxThreads) {
- this.maxThreads = maxThreads;
- return this;
- }
-
- public SessionHandler sessionHandler() {
- return sessionHandler;
- }
-
- /**
- * Set the SessionHandler to use. When not set one is created automatically.
- */
- public JettyServerConfig sessionHandler(SessionHandler sessionHandler) {
- this.sessionHandler = sessionHandler;
- return this;
- }
-
- public Handler contextHandler() {
- return contextHandler;
- }
-
- /**
- * Set the Jetty Handler to use. When not set one is created automatically.
- */
- public JettyServerConfig contextHandler(Handler contextHandler) {
- this.contextHandler = contextHandler;
- return this;
- }
-
- public Server server() {
- return server;
- }
-
- /**
- * Set the Jetty Server to use. When not set one is created automatically.
- */
- public JettyServerConfig server(Server server) {
- this.server = server;
- return this;
- }
-
- /**
- * Register a callback that is executed after the server and contextHandler have been
- * created but before the server has started.
- *
- * When we use this to register filters to the ServletContextHandler or perform other
- * changes prior to the server starting.
- */
- public JettyServerConfig register(Consumer callback) {
- configureCallback.add(callback);
- return this;
- }
-
- /**
- * Run configuration callbacks prior to starting the server.
- */
- void postConfigure() {
- for (Consumer callback : configureCallback) {
- callback.accept(this);
- }
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyStartServer.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyStartServer.java
deleted file mode 100644
index 4d572895..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JettyStartServer.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.Jex;
-import io.avaje.jex.spi.SpiRoutes;
-import io.avaje.jex.spi.SpiServiceManager;
-import io.avaje.jex.spi.SpiStartServer;
-
-/**
- * Configure and starts the underlying Jetty server.
- */
-public class JettyStartServer implements SpiStartServer {
-
- @Override
- public Jex.Server start(Jex jex, SpiRoutes routes, SpiServiceManager serviceManager) {
- return new JettyJexServer(jex, routes, serviceManager).start();
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java
deleted file mode 100644
index 33bd44f3..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHandler.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.Context;
-import io.avaje.jex.Jex;
-import io.avaje.jex.Routing;
-import io.avaje.jex.http.NotFoundResponse;
-import io.avaje.jex.spi.SpiContext;
-import io.avaje.jex.spi.SpiRoutes;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-
-import java.util.Map;
-
-class JexHandler extends AbstractHandler {
-
- //private static final String X_HTTP_METHOD_OVERRIDE = "X-HTTP-Method-Override";
- private final SpiRoutes routes;
- private final ServiceManager manager;
- private final StaticHandler staticHandler;
-
- JexHandler(Jex jex, SpiRoutes routes, ServiceManager manager, StaticHandler staticHandler) {
- this.routes = routes;
- this.manager = manager;
- this.staticHandler = staticHandler;
- }
-
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
- try {
- final Routing.Type routeType = method(req);
- final String uri = req.getRequestURI();
- SpiRoutes.Entry route = routes.match(routeType, uri);
- if (route == null) {
- var ctx = new JexHttpContext(manager, req, res, uri);
- routes.inc();
- try {
- processNoRoute(target, baseRequest, ctx, uri, routeType);
- routes.after(uri, ctx);
- } catch (Exception e) {
- handleException(ctx, e);
- } finally {
- routes.dec();
- }
- } else {
- final Map params = route.pathParams(uri);
- var ctx = new JexHttpContext(manager, req, res, route.matchPath(), params);
- route.inc();
- try {
- processRoute(ctx, uri, route);
- routes.after(uri, ctx);
- } catch (Exception e) {
- handleException(ctx, e);
- } finally {
- route.dec();
- }
- }
- } finally {
- baseRequest.setHandled(true);
- }
- }
-
- private void handleException(SpiContext ctx, Exception e) {
- manager.handleException(ctx, e);
- }
-
- private void processRoute(JexHttpContext ctx, String uri, SpiRoutes.Entry route) {
- routes.before(uri, ctx);
- ctx.setMode(null);
- route.handle(ctx);
- }
-
- private void processNoRoute(String target, Request baseRequest, JexHttpContext ctx, String uri, Routing.Type routeType) {
- routes.before(uri, ctx);
- if (routeType == Routing.Type.HEAD && hasGetHandler(uri)) {
- processHead(ctx);
- return;
- }
- if (routeType == Routing.Type.GET || routeType == Routing.Type.HEAD) {
- // check if handled by static resource
- if (staticHandler != null && staticHandler.handle(target, baseRequest, ctx.req(), ctx.res())) {
- return;
- }
- // todo: check if handled by singlePageHandler
- //if (config.inner.singlePageHandler.handle(ctx)) return@tryWithExceptionMapper
- }
-// if (routeType == Routing.Type.OPTIONS && isCorsEnabled(config)) { // CORS is enabled, so we return 200 for OPTIONS
-// return@tryWithExceptionMapper
-// }
-// if (prefer405) {
-// //&& availableHandlerTypes.isNotEmpty()
-// //val availableHandlerTypes = MethodNotAllowedUtil.findAvailableHttpHandlerTypes(matcher, requestUri)
-// //throw MethodNotAllowedResponse(details = MethodNotAllowedUtil.getAvailableHandlerTypes(ctx, availableHandlerTypes))
-// }
- throw new NotFoundResponse("uri: " + uri);
- }
-
- private void processHead(Context ctx) {
- ctx.status(200);
- }
-
- private boolean hasGetHandler(String uri) {
- return routes.match(Routing.Type.GET, uri) != null;
- }
-
- private Routing.Type method(HttpServletRequest req) {
- return manager.lookupRoutingType(req.getMethod());
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
deleted file mode 100644
index 3c1935af..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/JexHttpContext.java
+++ /dev/null
@@ -1,515 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.Context;
-import io.avaje.jex.Routing;
-import io.avaje.jex.UploadedFile;
-import io.avaje.jex.http.RedirectResponse;
-import io.avaje.jex.spi.HeaderKeys;
-import io.avaje.jex.spi.SpiContext;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.http.HttpSession;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.nio.charset.Charset;
-import java.time.Duration;
-import java.util.*;
-import java.util.stream.Stream;
-
-import static java.util.Collections.emptyList;
-import static java.util.Collections.emptyMap;
-
-class JexHttpContext implements SpiContext {
-
- private final ServiceManager mgr;
- protected final HttpServletRequest req;
- private final HttpServletResponse res;
- private final Map pathParams;
- private final String matchedPath;
- private String characterEncoding;
- private Routing.Type mode;
- private Map> formParamMap;
-
- JexHttpContext(ServiceManager mgr, HttpServletRequest req, HttpServletResponse res, String matchedPath) {
- this.mgr = mgr;
- this.req = req;
- this.res = res;
- this.matchedPath = matchedPath;
- this.pathParams = emptyMap();
- }
-
- JexHttpContext(ServiceManager mgr, HttpServletRequest req, HttpServletResponse res, String matchedPath, Map pathParams) {
- this.mgr = mgr;
- this.req = req;
- this.res = res;
- this.matchedPath = matchedPath;
- this.pathParams = pathParams;
- }
-
- @Override
- public void setMode(Routing.Type mode) {
- this.mode = mode;
- }
-
- private String characterEncoding() {
- if (characterEncoding == null) {
- characterEncoding = mgr.requestCharset(this);
- }
- return characterEncoding;
- }
-
- public HttpServletRequest req() {
- return req;
- }
-
- public HttpServletResponse res() {
- return res;
- }
-
- @Override
- public boolean isCommitted() {
- return res.isCommitted();
- }
-
- @Override
- public void reset() {
- res.reset();
- }
-
- @Override
- public Context attribute(String key, Object value) {
- req.setAttribute(key, value);
- return this;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T attribute(String key) {
- return (T) req.getAttribute(key);
- }
-
- @Override
- public String cookie(String name) {
- final jakarta.servlet.http.Cookie[] cookies = req.getCookies();
- if (cookies != null) {
- for (jakarta.servlet.http.Cookie cookie : cookies) {
- if (cookie.getName().equals(name)) {
- return cookie.getValue();
- }
- }
- }
- return null;
- }
-
- @Override
- public Map cookieMap() {
- final jakarta.servlet.http.Cookie[] cookies = req.getCookies();
- if (cookies == null) {
- return emptyMap();
- }
- final Map map = new LinkedHashMap<>();
- for (jakarta.servlet.http.Cookie cookie : cookies) {
- map.put(cookie.getName(), cookie.getValue());
- }
- return map;
- }
-
- @Override
- public Context cookie(Cookie cookie) {
- final jakarta.servlet.http.Cookie newCookie = new jakarta.servlet.http.Cookie(cookie.name(), cookie.value());
- newCookie.setPath(cookie.path());
- if (newCookie.getPath() == null) {
- newCookie.setPath("/");
- }
- final String domain = cookie.domain();
- if (domain != null) {
- newCookie.setDomain(domain);
- }
- final Duration duration = cookie.maxAge();
- if (duration != null) {
- newCookie.setMaxAge((int)duration.toSeconds());
- }
- newCookie.setHttpOnly(cookie.httpOnly());
- newCookie.setSecure(cookie.secure());
- res.addCookie(newCookie);
- return this;
- }
-
- @Override
- public Context cookie(String name, String value, int maxAge) {
- final jakarta.servlet.http.Cookie cookie = new jakarta.servlet.http.Cookie(name, value);
- cookie.setPath("/");
- cookie.setMaxAge(maxAge);
- res.addCookie(cookie);
- return this;
- }
-
- @Override
- public Context cookie(String name, String value) {
- return cookie(name, value, -1);
- }
-
- @Override
- public Context removeCookie(String name) {
- return removeCookie(name, null);
- }
-
- @Override
- public Context removeCookie(String name, String path) {
- if (path == null) {
- path = "/";
- }
- final jakarta.servlet.http.Cookie cookie = new jakarta.servlet.http.Cookie(name, "");
- cookie.setPath(path);
- cookie.setMaxAge(0);
- res.addCookie(cookie);
- return this;
- }
-
- @Override
- public void redirect(String location) {
- redirect(location, HttpServletResponse.SC_MOVED_TEMPORARILY);
- }
-
- @Override
- public void redirect(String location, int statusCode) {
- res.setHeader(HeaderKeys.LOCATION, location);
- status(statusCode);
- if (mode == Routing.Type.BEFORE) {
- throw new RedirectResponse(statusCode);
- }
- }
-
- @Override
- public void performRedirect() {
- // do nothing
- }
-
- @Override
- public String matchedPath() {
- return matchedPath;
- }
-
- @Override
- public InputStream inputStream() {
- try {
- return req.getInputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public T bodyAsClass(Class clazz) {
- return mgr.jsonRead(clazz, this);
- }
-
- @Override
- public byte[] bodyAsBytes() {
- return ContextUtil.readBody(req);
- }
-
- @Override
- public String body() {
- return new String(bodyAsBytes(), Charset.forName(characterEncoding()));
- }
-
- @Override
- public long contentLength() {
- return req.getContentLengthLong();
- }
-
- @Override
- public Map pathParamMap() {
- return pathParams;
- }
-
- @Override
- public String pathParam(String name) {
- return pathParams.get(name);
- }
-
- @Override
- public String queryParam(String name) {
- final String[] vals = req.getParameterValues(name);
- if (vals == null || vals.length == 0) {
- return null;
- } else {
- return vals[0];
- }
- }
-
- @Override
- public List queryParams(String name) {
- final String[] vals = req.getParameterValues(name);
- if (vals == null) {
- return emptyList();
- } else {
- return Arrays.asList(vals);
- }
- }
-
- @Override
- public Map queryParamMap() {
- final Map map = new LinkedHashMap<>();
- final Enumeration names = req.getParameterNames();
- while (names.hasMoreElements()) {
- final String key = names.nextElement();
- map.put(key, queryParam(key));
- }
- return map;
- }
-
- @Override
- public String queryString() {
- return req.getQueryString();
- }
-
- @Override
- public Map> formParamMap() {
- if (formParamMap == null) {
- formParamMap = initFormParamMap();
- }
- return formParamMap;
- }
-
- private Map> initFormParamMap() {
- if (isMultipartFormData()) {
- return mgr.multiPartForm(req);
- } else {
- return mgr.formParamMap(this, characterEncoding());
- }
- }
-
- @Override
- public String scheme() {
- return req.getScheme();
- }
-
- @Override
- public Context sessionAttribute(String key, Object value) {
- req.getSession().setAttribute(key, value);
- return this;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public T sessionAttribute(String key) {
- HttpSession session = req.getSession(false);
- return session == null ? null : (T) session.getAttribute(key);
- }
-
- @Override
- public Map sessionAttributeMap() {
- final Map map = new LinkedHashMap<>();
- final HttpSession session = req.getSession(false);
- if (session == null) {
- return emptyMap();
- }
- final Enumeration names = session.getAttributeNames();
- while (names.hasMoreElements()) {
- final String name = names.nextElement();
- map.put(name, session.getAttribute(name));
- }
- return map;
- }
-
- @Override
- public String url() {
- return req.getRequestURL().toString();
- }
-
- @Override
- public String fullUrl() {
- final String url = url();
- final String qs = queryString();
- return qs == null ? url : url + "?" + qs;
- }
-
- @Override
- public String contextPath() {
- String path = req.getContextPath();
- return path == null ? "" : path;
- }
-
- @Override
- public Context status(int statusCode) {
- res.setStatus(statusCode);
- return this;
- }
-
- @Override
- public int status() {
- return res.getStatus();
- }
-
- @Override
- public String contentType() {
- return req.getContentType();
- }
-
- @Override
- public Context contentType(String contentType) {
- res.setContentType(contentType);
- return this;
- }
-
- public Map headerMap() {
- Map map = new LinkedHashMap<>();
- final Enumeration names = req.getHeaderNames();
- while (names.hasMoreElements()) {
- final String name = names.nextElement();
- map.put(name, req.getHeader(name));
- }
- return map;
- }
-
- @Override
- public String responseHeader(String key) {
- return req.getHeader(key);
- }
-
- @Override
- public String header(String key) {
- return req.getHeader(key);
- }
-
- @Override
- public Context header(String key, String value) {
- res.setHeader(key, value);
- return this;
- }
-
- @Override
- public String host() {
- return req.getHeader(HeaderKeys.HOST);
- }
-
- @Override
- public String ip() {
- return req.getRemoteAddr();
- }
-
- @Override
- public boolean isMultipart() {
- final String type = header(HeaderKeys.CONTENT_TYPE);
- return type != null && type.toLowerCase().contains("multipart/");
- }
-
- @Override
- public boolean isMultipartFormData() {
- final String type = header(HeaderKeys.CONTENT_TYPE);
- return type != null && type.toLowerCase().contains("multipart/form-data");
- }
-
- @Override
- public String method() {
- return req.getMethod();
- }
-
- @Override
- public String path() {
- return req.getRequestURI();
- }
-
- @Override
- public int port() {
- return req.getServerPort();
- }
-
- @Override
- public String protocol() {
- return req.getProtocol();
- }
-
- @Override
- public Context json(Object bean) {
- contentType(APPLICATION_JSON);
- mgr.jsonWrite(bean, this);
- return this;
- }
-
- @Override
- public Context jsonStream(Stream stream) {
- contentType(APPLICATION_X_JSON_STREAM);
- mgr.jsonWriteStream(stream, this);
- return this;
- }
-
- @Override
- public Context jsonStream(Iterator iterator) {
- contentType(APPLICATION_X_JSON_STREAM);
- mgr.jsonWriteStream(iterator, this);
- return this;
- }
-
- /**
- * Write plain text content to the response.
- */
- @Override
- public Context text(String content) {
- contentType(TEXT_PLAIN);
- return write(content);
- }
-
- /**
- * Write html content to the response.
- */
- @Override
- public Context html(String content) {
- contentType(TEXT_HTML);
- return write(content);
- }
-
- @Override
- public Context write(String content) {
- try {
- res.getWriter().write(content);
- return this;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public Context render(String name, Map model) {
- mgr.render(this, name, model);
- return this;
- }
-
- @Override
- public OutputStream outputStream() {
- try {
- return res.getOutputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public UploadedFile uploadedFile(String name) {
- final List files = uploadedFiles(name);
- return files.isEmpty() ? null : files.get(0);
- }
-
- @Override
- public List uploadedFiles(String name) {
- if (!isMultipartFormData()) {
- return emptyList();
- } else {
- return mgr.uploadedFiles(req, name);
- }
- }
-
- @Override
- public List uploadedFiles() {
- if (!isMultipartFormData()) {
- return emptyList();
- } else {
- return mgr.uploadedFiles(req);
- }
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java
deleted file mode 100644
index dea863bb..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/MultipartUtil.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.UploadedFile;
-import jakarta.servlet.MultipartConfigElement;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.Part;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UncheckedIOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-
-class MultipartUtil {
-
- private final MultipartConfigElement config;
-
- MultipartUtil(MultipartConfigElement config) {
- this.config = config;
- }
-
- private void setConfig(HttpServletRequest req) {
- req.setAttribute("org.eclipse.jetty.multipartConfig", config);
- }
-
- List uploadedFiles(HttpServletRequest req) {
- try {
- setConfig(req);
- return req.getParts().stream()
- .filter(part -> isFile(part))
- .map(this::toUploaded)
- .collect(toList());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- List uploadedFiles(HttpServletRequest req, String partName) {
- try {
- setConfig(req);
- return req.getParts().stream()
- .filter(part -> part.getName().equals(partName) && isFile(part))
- .map(this::toUploaded)
- .collect(toList());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- UploadedFile toUploaded(Part part) {
- return new PartUploadedFile(part);
- }
-
- Map> fieldMap(HttpServletRequest req) {
- setConfig(req);
- try {
- Map> map = new LinkedHashMap<>();
- for (Part part : req.getParts()) {
- if (isField(part)) {
- final String name = part.getName();
- final String value = readAsString(part);
- map.computeIfAbsent(name, s -> new ArrayList<>()).add(value);
- }
- }
- return map;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (ServletException e) {
- throw new RuntimeException(e);
- }
- }
-
- private String readAsString(Part part) {
- try {
- return new BufferedReader(new InputStreamReader(part.getInputStream(), StandardCharsets.UTF_8))
- .lines()
- .collect(joining("\n"));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private static boolean isFile(Part filePart) {
- return !isField(filePart);
- }
-
- private static boolean isField(Part filePart) {
- return filePart.getSubmittedFileName() == null; // this is what Apache FileUpload does ...
- }
-
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
deleted file mode 100644
index 712ed3b6..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/PartUploadedFile.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.UploadedFile;
-import jakarta.servlet.http.Part;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-
-/**
- * UploadedFile using servlet Part.
- */
-class PartUploadedFile implements UploadedFile {
-
- private final Part part;
-
- PartUploadedFile(Part part) {
- this.part = part;
- }
-
- @Override
- public String name() {
- return part.getName();
- }
-
- @Override
- public String fileName() {
- return part.getSubmittedFileName();
- }
-
- @Override
- public InputStream content() {
- try {
- return part.getInputStream();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public String contentType() {
- return part.getContentType();
- }
-
- @Override
- public long size() {
- return part.getSize();
- }
-
- @Override
- public void delete() {
- try {
- part.delete();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public String toString() {
- return "name:" + name() + " fileName:" + fileName() + " size:" + size();
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java
deleted file mode 100644
index 5eb0ddbc..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/ServiceManager.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.UploadedFile;
-import io.avaje.jex.spi.ProxyServiceManager;
-import io.avaje.jex.spi.SpiServiceManager;
-import jakarta.servlet.http.HttpServletRequest;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * Jetty specific service manager.
- */
-class ServiceManager extends ProxyServiceManager {
-
- private final MultipartUtil multipartUtil;
-
- ServiceManager(SpiServiceManager delegate, MultipartUtil multipartUtil) {
- super(delegate);
- this.multipartUtil = multipartUtil;
- }
-
- List uploadedFiles(HttpServletRequest req) {
- return multipartUtil.uploadedFiles(req);
- }
-
- List uploadedFiles(HttpServletRequest req, String name) {
- return multipartUtil.uploadedFiles(req, name);
- }
-
- Map> multiPartForm(HttpServletRequest req) {
- return multipartUtil.fieldMap(req);
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java
deleted file mode 100644
index 3694c115..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandler.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.StaticFileSource;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.util.resource.EmptyResource;
-import org.eclipse.jetty.util.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-class StaticHandler {
-
- private static final Logger log = LoggerFactory.getLogger(StaticHandler.class);
-
- private final List handlers = new ArrayList<>();
- private final Server server;
- private final boolean preCompress;
-
- StaticHandler(boolean preCompress, Server server) {
- this.preCompress = preCompress;
- this.server = server;
- }
-
- void addStaticFileConfig(StaticFileSource config) {
- ResourceHandler handler;
- if ("/webjars".equals(config.getPath())) {
- handler = new WebjarHandler();
- } else {
- PrefixableHandler h = new PrefixableHandler(config.getUrlPathPrefix());
- h.setResourceBase(getResourcePath(config));
- h.setDirAllowed(false);
- h.setEtags(true);
- handler = h;
- }
- log.info("Static file handler added {}", config);
-
- try {
- handler.setServer(server);
- handler.start();
- } catch (Exception e) {
- throw new RuntimeException("Error starting Jetty static resource handler", e);
- }
- handlers.add(handler);
- }
-
- private String getResourcePath(StaticFileSource config) {
- if (config.getLocation() == StaticFileSource.Location.CLASSPATH) {
- var resource = Resource.newClassPathResource(config.getPath());
- if (resource == null) {
- throw new RuntimeException(noSuchDir(config) + " Depending on your setup, empty folders might not get copied to classpath.");
- }
- return resource.toString();
- }
- final File path = new File(config.getPath());
- if (!path.exists()) {
- throw new RuntimeException(noSuchDir(config) + " path: " + path.getAbsolutePath());
- }
- return config.getPath();
- }
-
- private String noSuchDir(StaticFileSource config) {
- return "Static resource directory with path: '" + config.getPath() + "' does not exist.";
- }
-
- boolean handle(String target, Request baseRequest, HttpServletRequest req, HttpServletResponse res) {
- for (ResourceHandler handler : handlers) {
- try {
- var resource = handler.getResource(target);
- if (isFile(resource) || isDirectoryWithWelcomeFile(resource, handler, target)) {
-// val maxAge = if (target.startsWith("/immutable/") || handler is WebjarHandler) 31622400 else 0
-// httpResponse.setHeader(HeaderKeys.CACHE_CONTROL, "max-age=$maxAge");
-
- // Remove the default content type because Jetty will not set the correct one
- // if the HTTP response already has a content type set
-// if (precompressStaticFiles && PrecompressingResourceHandler.handle(resource, httpRequest, httpResponse)) {
-// return true
-// }
- res.setContentType(null);
- handler.handle(target, baseRequest, req, res);
- req.setAttribute("handled-as-static-file", true);
-// (httpResponse as JavalinResponseWrapper).outputStream.finalize()
- return true;
- }
- } catch (Exception e) { // it's fine
-// if (!Util.isClientAbortException(e)) {
-// Javalin.log?.error("Exception occurred while handling static resource", e)
-// }
- log.error("Exception occurred while handling static resource", e);
- }
- }
- return false;
- }
-
- private boolean isFile(Resource resource) {
- return resource != null && resource.exists() && !resource.isDirectory();
- }
-
- private boolean isDirectoryWithWelcomeFile(Resource resource, ResourceHandler handler, String target) {
- //String path = target.removeSuffix("/")+"/index.html";
- if (target.endsWith("/")) {
- target = target.substring(0, target.length() - 1);
- }
- String path = target + "/index.html";
- if (resource == null || !resource.isDirectory()) {
- return false;
- }
- try {
- final Resource indexHtml = handler.getResource(path);
- return indexHtml != null && indexHtml.exists();
- } catch (IOException e) {
- log.warn("Error checking for welcome file", e);
- return false;
- }
- }
-
- private static class WebjarHandler extends ResourceHandler {
- @Override
- public Resource getResource(String path) throws IOException {
- final Resource resource = Resource.newClassPathResource("META-INF/resources" + path);
- return (resource != null) ? resource : super.getResource(path);
- }
- }
-
- private static class PrefixableHandler extends ResourceHandler {
-
- private final String urlPathPrefix;
-
- PrefixableHandler(String urlPathPrefix) {
- this.urlPathPrefix = urlPathPrefix;
- }
-
- @Override
- public Resource getResource(String path) throws IOException {
- if (urlPathPrefix.equals("/")) {
- return super.getResource(path); // same as regular ResourceHandler
- }
- String targetPath = target(path);
- if ("".equals(targetPath)) {
- return super.getResource("/"); // directory without trailing '/'
- }
- if (!path.startsWith(urlPathPrefix)) {
- return EmptyResource.INSTANCE;
- }
- if (!targetPath.startsWith("/")) {
- return EmptyResource.INSTANCE;
- } else {
- return super.getResource(targetPath);
- }
- }
-
- private String target(String path) {
- if (path.startsWith(urlPathPrefix)) {
- return path.substring(urlPathPrefix.length());
- } else {
- return path;
- }
- }
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandlerFactory.java b/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandlerFactory.java
deleted file mode 100644
index 5d9da4af..00000000
--- a/avaje-jex-jetty/src/main/java/io/avaje/jex/jetty/StaticHandlerFactory.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.avaje.jex.jetty;
-
-import io.avaje.jex.Jex;
-import io.avaje.jex.StaticFileSource;
-import org.eclipse.jetty.server.Server;
-
-import java.util.List;
-
-class StaticHandlerFactory {
-
- StaticHandler build(Server server, Jex jex, List sourceList) {
- StaticHandler handler = new StaticHandler(jex.config().preCompressStaticFiles(), server);
- for (StaticFileSource source : sourceList) {
- handler.addStaticFileConfig(source);
- }
- return handler;
- }
-}
diff --git a/avaje-jex-jetty/src/main/java/module-info.java b/avaje-jex-jetty/src/main/java/module-info.java
deleted file mode 100644
index 8dbb3de8..00000000
--- a/avaje-jex-jetty/src/main/java/module-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-import io.avaje.jex.jetty.JettyStartServer;
-import io.avaje.jex.spi.SpiStartServer;
-
-module io.avaje.jex.jetty {
-
- exports io.avaje.jex.jetty;
-
- requires transitive io.avaje.jex;
- //requires io.avaje.jex.jettyx;
- requires java.net.http;
- requires transitive jetty.servlet.api;
- requires transitive org.slf4j;
- requires transitive org.eclipse.jetty.http;
- requires transitive org.eclipse.jetty.server;
- requires transitive org.eclipse.jetty.io;
- requires transitive org.eclipse.jetty.util;
-
-
- provides SpiStartServer with JettyStartServer;
-}
diff --git a/avaje-jex-jetty/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer b/avaje-jex-jetty/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer
deleted file mode 100644
index 8adaab64..00000000
--- a/avaje-jex-jetty/src/main/resources/META-INF/services/io.avaje.jex.spi.SpiStartServer
+++ /dev/null
@@ -1 +0,0 @@
-io.avaje.jex.jetty.JettyStartServer
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AppRoles.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AppRoles.java
deleted file mode 100644
index 1ab3f369..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AppRoles.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Role;
-
-/**
- * Create an App specific enum that implements Role.
- */
-public enum AppRoles implements Role {
- ADMIN,
- USER
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AutoCloseIterator.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AutoCloseIterator.java
deleted file mode 100644
index c613db09..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/AutoCloseIterator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package io.avaje.jex.base;
-
-import java.util.Iterator;
-
-public class AutoCloseIterator implements Iterator, AutoCloseable {
-
- private final Iterator it;
- private boolean closed;
-
- public AutoCloseIterator(Iterator it) {
- this.it = it;
- }
-
- @Override
- public boolean hasNext() {
- return it.hasNext();
- }
-
- @Override
- public E next() {
- return it.next();
- }
-
- @Override
- public void close() {
- closed = true;
- }
-
- public boolean isClosed() {
- return closed;
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/CharacterEncodingTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/CharacterEncodingTest.java
deleted file mode 100644
index 9fd11298..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/CharacterEncodingTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class CharacterEncodingTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- Jex app = Jex.create()
- .routing(routing -> routing
- .get("/text", ctx -> ctx.contentType("text/plain;charset=utf-8").write("суп из капусты"))
- .get("/json", ctx -> ctx.json("白菜湯"))
- .get("/html", ctx -> ctx.html("kålsuppe")));
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
-
- var textRes = pair.request().path("text").GET().asString();
- var jsonRes = pair.request().path("json").GET().asString();
- var htmlRes = pair.request().path("html").GET().asString();
-
- assertThat(contentType(jsonRes)).isEqualTo("application/json");
- assertThat(contentType(htmlRes)).isEqualTo("text/html;charset=utf-8");
- assertThat(jsonRes.body()).isEqualTo("\"白菜湯\"");
- assertThat(htmlRes.body()).isEqualTo("kålsuppe");
-
- assertThat(contentType(textRes)).isEqualTo("text/plain;charset=utf-8");
- assertThat(textRes.body()).isEqualTo("суп из капусты");
- }
-
- private String contentType(HttpResponse res) {
- return res.headers().firstValue("Content-Type").get();
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextAttributeTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextAttributeTest.java
deleted file mode 100644
index 4035832b..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextAttributeTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-import java.util.UUID;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextAttributeTest {
-
- static final UUID uuid = UUID.randomUUID();
-
- static TestPair pair = init();
-
- static TestPair attrPair;
- static UUID attrUuid;
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .before( ctx -> ctx.attribute("oneUuid", uuid).attribute(TestPair.class.getName(), pair))
- .get("/", ctx -> {
- attrUuid = ctx.attribute("oneUuid");
- attrPair = ctx.attribute(TestPair.class.getName());
-
- assert attrUuid == uuid;
- assert attrPair == pair;
- ctx.text("all-good");
- })
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("all-good");
-
- assertThat(attrPair).isSameAs(pair);
- assertThat(attrUuid).isSameAs(uuid);
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextCookieTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextCookieTest.java
deleted file mode 100644
index a01e72f1..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextCookieTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Context;
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextCookieTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .get("/setCookie", ctx -> ctx.cookie("ck", "val").cookie("ck2", "val2"))
- .get("/readCookie/{name}", ctx -> ctx.text("readCookie:" + ctx.cookie(ctx.pathParam("name"))))
- .get("/readCookieMap", ctx -> ctx.text("cookieMap:" + ctx.cookieMap()))
- .get("/removeCookie/{name}", ctx -> ctx.removeCookie(ctx.pathParam("name")).text("ok"))
- .get("/setCookieAll", ctx -> {
- final Context.Cookie cookie = Context.Cookie.of("ac", "v_all")
- .path("/").httpOnly(true).maxAge(Duration.of(10, ChronoUnit.DAYS));
- ctx.cookie(cookie);
- })
- );
- return TestPair.create(app, 9001);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void set_read_readMap_remove_readMap_remove_readMap() {
- HttpResponse res = pair.request().path("removeCookie").path("ac").GET().asString();
- assertThat(res.body()).isEqualTo("ok");
-
- res = pair.request().path("setCookie").GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
-
- res = pair.request().path("readCookie").path("ck").GET().asString();
- assertThat(res.body()).isEqualTo("readCookie:val");
-
- res = pair.request().path("readCookie").path("ck2").GET().asString();
- assertThat(res.body()).isEqualTo("readCookie:val2");
-
- res = pair.request().path("readCookieMap").GET().asString();
- assertThat(res.body()).isEqualTo("cookieMap:{ck=val, ck2=val2}");
-
- res = pair.request().path("removeCookie").path("ck").GET().asString();
- assertThat(res.body()).isEqualTo("ok");
-
- res = pair.request().path("readCookieMap").GET().asString();
- assertThat(res.body()).isEqualTo("cookieMap:{ck2=val2}");
-
- res = pair.request().path("removeCookie").path("ck2").GET().asString();
- assertThat(res.body()).isEqualTo("ok");
-
- res = pair.request().path("readCookieMap").GET().asString();
- assertThat(res.body()).isEqualTo("cookieMap:{}");
- }
-
- @Test
- void setAll() {
- HttpResponse res = pair.request().path("setCookieAll").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
-
- res = pair.request().path("readCookieMap").GET().asString();
- assertThat(res.body()).isEqualTo("cookieMap:{ac=v_all}");
-
- res = pair.request().path("readCookie").path("ac").GET().asString();
- assertThat(res.body()).isEqualTo("readCookie:v_all");
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextLengthTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextLengthTest.java
deleted file mode 100644
index a7b7c0cb..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextLengthTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextLengthTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .post("/", ctx -> ctx.text("contentLength:" + ctx.contentLength() + " type:" + ctx.contentType()))
- .get("/url", ctx -> ctx.text("url:" + ctx.url()))
- .get("/fullUrl", ctx -> ctx.text("fullUrl:" + ctx.fullUrl()))
- .get("/contextPath", ctx -> ctx.text("contextPath:" + ctx.contextPath()))
- .get("/userAgent", ctx -> ctx.text("userAgent:" + ctx.userAgent()))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void when_noReqContentType() {
- HttpResponse res = pair.request().body("MyBodyContent")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contentLength:13 type:null");
- }
-
- @Test
- void requestContentLengthAndType_notReqContentType() {
- HttpResponse res = pair.request()
- .formParam("a", "my-a-val")
- .formParam("b", "my-b-val")
- .POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contentLength:21 type:application/x-www-form-urlencoded");
- }
-
- @Test
- void url() {
- HttpResponse res = pair.request()
- .path("url")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("url:http://localhost:" + pair.port() + "/url");
- }
-
- @Test
- void fullUrl_no_queryString() {
- HttpResponse res = pair.request()
- .path("fullUrl")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("fullUrl:http://localhost:" + pair.port() + "/fullUrl");
- }
-
- @Test
- void fullUrl_queryString() {
- HttpResponse res = pair.request()
- .path("fullUrl")
- .queryParam("a", "av")
- .queryParam("b", "bv")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("fullUrl:http://localhost:" + pair.port() + "/fullUrl?a=av&b=bv");
- }
-
- @Test
- void contextPath() {
- HttpResponse res = pair.request()
- .path("contextPath")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("contextPath:");
- }
-
- @Test
- void userAgent() {
- HttpResponse res = pair.request()
- .path("userAgent")
- .queryParam("a", "av")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).contains("userAgent:Java-http-client");
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextTest.java
deleted file mode 100644
index faa77f74..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ContextTest.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-import java.util.Optional;
-
-import static java.util.Objects.requireNonNull;
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ContextTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- final Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.text("ze-get"))
- .post("/", ctx -> ctx.text("ze-post"))
- .get("/header", ctx -> {
- ctx.header("From-My-Server", "Set-By-Server");
- ctx.text("req-header[" + ctx.header("From-My-Client") + "]");
- })
- .get("/headerMap", ctx -> ctx.text("req-header-map[" + ctx.headerMap() + "]"))
- .get("/host", ctx -> {
- final String host = ctx.host();
- requireNonNull(host);
- ctx.text("host:" + host);
- })
- .get("/ip", ctx -> {
- final String ip = ctx.ip();
- requireNonNull(ip);
- ctx.text("ip:" + ip);
- })
- .post("/multipart", ctx -> ctx.text("isMultipart:" + ctx.isMultipart() + " isMultipartFormData:" + ctx.isMultipartFormData()))
- .get("/method", ctx -> ctx.text("method:" + ctx.method() + " path:" + ctx.path() + " protocol:" + ctx.protocol() + " port:" + ctx.port()))
- .post("/echo", ctx -> ctx.text("req-body[" + ctx.body() + "]"))
- .get("/{a}/{b}", ctx -> ctx.text("ze-get-" + ctx.pathParamMap()))
- .post("/{a}/{b}", ctx -> ctx.text("ze-post-" + ctx.pathParamMap()))
- .get("/status", ctx -> {
- ctx.status(201);
- ctx.text("status:" + ctx.status());
- }));
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void health_liveness() {
- HttpResponse res = pair.request().path("health/liveness").GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("ok");
- }
-
- @Test
- void health_readiness() {
- HttpResponse res = pair.request().path("health/readiness").GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("ok");
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.body()).isEqualTo("ze-get");
- }
-
- @Test
- void post() {
- HttpResponse res = pair.request().body("simple").POST().asString();
- assertThat(res.body()).isEqualTo("ze-post");
- }
-
- @Test
- void ctx_header_getSet() {
- HttpResponse res = pair.request().path("header")
- .header("From-My-Client", "client-value")
- .GET().asString();
-
- final Optional serverSetHeader = res.headers().firstValue("From-My-Server");
- assertThat(serverSetHeader.get()).isEqualTo("Set-By-Server");
- assertThat(res.body()).isEqualTo("req-header[client-value]");
- }
-
- @Test
- void ctx_headerMap() {
- HttpResponse res = pair.request().path("headerMap")
- .header("X-Foo", "a")
- .header("X-Bar", "b")
- .GET().asString();
-
- assertThat(res.body()).contains("X-Foo=a");
- assertThat(res.body()).contains("X-Bar=b");
- }
-
- @Test
- void ctx_status() {
- HttpResponse res = pair.request().path("status")
- .GET().asString();
-
- assertThat(res.body()).isEqualTo("status:201");
- }
-
- @Test
- void ctx_host() {
- HttpResponse res = pair.request().path("host")
- .GET().asString();
-
- assertThat(res.body()).contains("host:localhost");
- }
-
- @Test
- void ctx_ip() {
- HttpResponse res = pair.request().path("ip")
- .GET().asString();
-
- assertThat(res.body()).isEqualTo("ip:127.0.0.1");
- }
-
- @Test
- void ctx_isMultiPart_when_not() {
- HttpResponse res = pair.request().path("multipart")
- .formParam("a", "aval")
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("isMultipart:false isMultipartFormData:false");
- }
-
-
- @Test
- void ctx_isMultiPart_when_nothing() {
- HttpResponse res = pair.request().path("multipart")
- .body("junk")
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("isMultipart:false isMultipartFormData:false");
- }
-
- @Test
- void ctx_isMultiPart_when_isMultipart() {
- HttpResponse res = pair.request().path("multipart")
- .header("Content-Type", "multipart/foo")
- .body("junk")
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("isMultipart:true isMultipartFormData:false");
- }
-
- @Test
- void ctx_isMultiPart_when_isMultipartFormData() {
- HttpResponse res = pair.request().path("multipart")
- .header("Content-Type", "multipart/form-data")
- .body("junk")
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("isMultipart:true isMultipartFormData:true");
- }
-
- @Test
- void ctx_methodPathPortProtocol() {
- HttpResponse res = pair.request().path("method")
- .GET().asString();
-
- assertThat(res.body()).isEqualTo("method:GET path:/method protocol:HTTP/1.1 port:" + pair.port());
- }
-
- @Test
- void post_body() {
- HttpResponse res = pair.request().path("echo").body("simple").POST().asString();
- assertThat(res.body()).isEqualTo("req-body[simple]");
- }
-
- @Test
- void get_path_path() {
- var res = pair.request()
- .path("A").path("B").GET().asString();
-
- assertThat(res.body()).isEqualTo("ze-get-{a=A, b=B}");
-
- res = pair.request()
- .path("one").path("bar").body("simple").POST().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("ze-post-{a=one, b=bar}");
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ExceptionManagerTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ExceptionManagerTest.java
deleted file mode 100644
index 29358ec6..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/ExceptionManagerTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import io.avaje.jex.http.ConflictResponse;
-import io.avaje.jex.http.ForbiddenResponse;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class ExceptionManagerTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- final Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> {
- throw new ForbiddenResponse();
- })
- .post("/", ctx -> {
- throw new IllegalStateException("foo");
- })
- .get("/conflict", ctx -> {
- throw new ConflictResponse("Baz");
- })
- .get("/fiveHundred", ctx -> {
- throw new IllegalArgumentException("Bar");
- }))
- .exception(NullPointerException.class, (exception, ctx) -> ctx.text("npe"))
- .exception(IllegalStateException.class, (exception, ctx) -> ctx.status(222).text("Handled IllegalStateException|" + exception.getMessage()))
- .exception(ForbiddenResponse.class, (exception, ctx) -> ctx.status(223).text("Handled ForbiddenResponse|" + exception.getMessage()));
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.statusCode()).isEqualTo(223);
- assertThat(res.body()).isEqualTo("Handled ForbiddenResponse|Forbidden");
- }
-
- @Test
- void post() {
- HttpResponse res = pair.request().body("simple").POST().asString();
- assertThat(res.statusCode()).isEqualTo(222);
- assertThat(res.body()).isEqualTo("Handled IllegalStateException|foo");
- }
-
- @Test
- void expect_fallback_to_default_asPlainText() {
- HttpResponse res = pair.request().path("conflict").GET().asString();
- assertThat(res.statusCode()).isEqualTo(409);
- assertThat(res.body()).isEqualTo("Baz");
- assertThat(res.headers().firstValue("Content-Type").get()).contains("text/plain");
- }
-
- @Test
- void expect_fallback_to_default_asJson() {
- HttpResponse res = pair.request().path("conflict").header("Accept", "application/json").GET().asString();
- assertThat(res.statusCode()).isEqualTo(409);
- assertThat(res.body()).isEqualTo("{\"title\": Baz, \"status\": 409}");
- assertThat(res.headers().firstValue("Content-Type").get()).contains("application/json");
- }
-
- @Test
- void expect_fallback_to_internalServerError() {
- HttpResponse res = pair.request().path("fiveHundred").GET().asString();
- assertThat(res.statusCode()).isEqualTo(500);
- assertThat(res.body()).isEqualTo("Internal server error");
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/FilterTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/FilterTest.java
deleted file mode 100644
index 550eded8..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/FilterTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpHeaders;
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class FilterTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- final Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.text("roo"))
- .get("/one", ctx -> ctx.text("one"))
- .get("/two", ctx -> ctx.text("two"))
- .get("/two/{id}", ctx -> ctx.text("two-id"))
- .before(ctx -> ctx.header("before-all", "set"))
- .before("/two/*", ctx -> ctx.header("before-two", "set"))
- .after(ctx -> ctx.header("after-all", "set"))
- .after("/two/*", ctx -> ctx.header("after-two", "set"))
- .get("/dummy", ctx -> ctx.text("dummy"))
- );
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
-
- res = pair.request().path("one").GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
-
- res = pair.request().path("two").GET().asString();
- assertHasBeforeAfterAll(res);
- assertNoBeforeAfterTwo(res);
- }
-
-
- @Test
- void get_two_expect_extraFilters() {
- HttpResponse res = pair.request()
- .path("two/42").GET().asString();
-
- final HttpHeaders headers = res.headers();
- assertHasBeforeAfterAll(res);
- assertThat(headers.firstValue("before-two")).get().isEqualTo("set");
- assertThat(headers.firstValue("after-two")).get().isEqualTo("set");
- }
-
- private void assertNoBeforeAfterTwo(HttpResponse res) {
- assertThat(res.headers().firstValue("before-two")).isEmpty();
- assertThat(res.headers().firstValue("after-two")).isEmpty();
- }
-
- private void assertHasBeforeAfterAll(HttpResponse res) {
- assertThat(res.headers().firstValue("before-all")).get().isEqualTo("set");
- assertThat(res.headers().firstValue("after-all")).get().isEqualTo("set");
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/HelloDto.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/HelloDto.java
deleted file mode 100644
index 6e892c1c..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/HelloDto.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.avaje.jex.base;
-
-public class HelloDto {
-
- public long id;
- public String name;
-
- @Override
- public String toString() {
- return "id:" + id + " name:" + name;
- }
-
- public static HelloDto rob() {
- return create(42, "rob");
- }
-
- public static HelloDto fi() {
- return create(45, "fi");
- }
-
- public static HelloDto create(long id, String name) {
- HelloDto me = new HelloDto();
- me.id = id;
- me.name = name;
- return me;
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/JsonTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/JsonTest.java
deleted file mode 100644
index e7d3085a..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/JsonTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpHeaders;
-import java.net.http.HttpResponse;
-import java.util.List;
-import java.util.stream.Stream;
-
-import static java.util.Arrays.asList;
-import static java.util.stream.Collectors.toList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-class JsonTest {
-
- static List HELLO_BEANS = asList(HelloDto.rob(), HelloDto.fi());
-
- static AutoCloseIterator ITERATOR = createBeanIterator();
-
- private static AutoCloseIterator createBeanIterator() {
- return new AutoCloseIterator<>(HELLO_BEANS.iterator());
- }
-
- static TestPair pair = init();
-
- static TestPair init() {
- Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.json(HelloDto.rob()).status(200))
- .get("/iterate", ctx -> ctx.jsonStream(ITERATOR))
- .get("/stream", ctx -> ctx.jsonStream(HELLO_BEANS.stream()))
- .post("/", ctx -> ctx.text("bean[" + ctx.bodyAsClass(HelloDto.class) + "]")));
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
-
- var bean = pair.request()
- .GET()
- .bean(HelloDto.class);
-
- assertThat(bean.id).isEqualTo(42);
- assertThat(bean.name).isEqualTo("rob");
-
- final HttpResponse hres = pair.request()
- .GET().asString();
-
- final HttpHeaders headers = hres.headers();
- assertThat(headers.firstValue("Content-Type").get()).isEqualTo("application/json");
- }
-
- @Test
- void stream_viaIterator() {
- final Stream beanStream = pair.request()
- .path("iterate")
- .GET()
- .stream(HelloDto.class);
-
- // expect client gets the expected stream of beans
- assertCollectedStream(beanStream);
- // assert AutoCloseable iterator on the server-side was closed
- assertThat(ITERATOR.isClosed()).isTrue();
- }
-
- @Test
- void stream() {
- final Stream beanStream = pair.request()
- .path("stream")
- .GET()
- .stream(HelloDto.class);
-
- assertCollectedStream(beanStream);
- }
-
- private void assertCollectedStream(Stream beanStream) {
- final List collectedBeans = beanStream.collect(toList());
- assertThat(collectedBeans).hasSize(2);
-
- final HelloDto first = collectedBeans.get(0);
- assertThat(first.id).isEqualTo(42);
- assertThat(first.name).isEqualTo("rob");
-
- final HelloDto second = collectedBeans.get(1);
- assertThat(second.id).isEqualTo(45);
- assertThat(second.name).isEqualTo("fi");
- }
-
- @Test
- void post() {
- HelloDto dto = new HelloDto();
- dto.id = 42;
- dto.name = "rob was here";
-
- var res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:42 name:rob was here]");
- assertThat(res.statusCode()).isEqualTo(200);
-
- dto.id = 99;
- dto.name = "fi";
-
- res = pair.request()
- .body(dto)
- .POST().asString();
-
- assertThat(res.body()).isEqualTo("bean[id:99 name:fi]");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/MultipartFormPostTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/MultipartFormPostTest.java
deleted file mode 100644
index 69b202f0..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/MultipartFormPostTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package io.avaje.jex.base;
-
-import com.mashape.unirest.http.Unirest;
-import com.mashape.unirest.http.exceptions.UnirestException;
-import io.avaje.jex.Jex;
-import io.avaje.jex.UploadedFile;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class MultipartFormPostTest {
-
- static TestPair pair = init();
-
- static final File helloFile = new File("src/test/resources/static-a/hello.txt");
- static final File hello2File = new File("src/test/resources/static-a/hello2.txt");
-
- static TestPair init() {
- final Jex app = Jex.create()
- .routing(routing -> routing
- .post("/simple", ctx -> {
- final UploadedFile file = ctx.uploadedFile("one");
- ctx.text("nm:" + file.name() + " fn:" + file.fileName() + " size:" + file.size());
- })
- .post("/both", ctx -> {
- final UploadedFile file = ctx.uploadedFile("one");
- ctx.text("nm:" + file.name() + " fn:" + file.fileName() + " size:" + file.size() + " paramMap:" + ctx.formParamMap());
- })
- .post("/multi", ctx -> {
- String out = "";
- final List files = ctx.uploadedFiles("one");
- for (UploadedFile file : files) {
- out += "file[nm:" + file.name() + " fn:" + file.fileName() + " size:" + file.size() + "]";
- }
- ctx.text(out + " paramMap:" + ctx.formParamMap());
- })
- .post("/multiAll", ctx -> {
- String out = "";
- final List files = ctx.uploadedFiles();
- for (UploadedFile file : files) {
- out += "file[nm:" + file.name() + " fn:" + file.fileName() + " size:" + file.size() + "]";
- }
- ctx.text(out);
- })
- .post("/delete", ctx -> {
- final UploadedFile file = ctx.uploadedFile("one");
- file.delete();
- ctx.text("withDelete nm:" + file.name() + " fn:" + file.fileName() + " size:" + file.size());
- })
- );
-
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void simple() throws UnirestException {
- final String baseUrl = pair.url();
-
- final com.mashape.unirest.http.HttpResponse res =
- Unirest.post(baseUrl + "/simple")
- .field("one", helloFile)
- .asString();
-
- assertThat(res.getBody()).isEqualTo("nm:one fn:hello.txt size:" + helloFile.length());
- }
-
- @Test
- void delete() throws UnirestException {
- final String baseUrl = pair.url();
-
- final com.mashape.unirest.http.HttpResponse res =
- Unirest.post(baseUrl + "/delete")
- .field("one", helloFile)
- .asString();
-
- assertThat(res.getBody()).isEqualTo("withDelete nm:one fn:hello.txt size:" + helloFile.length());
- }
-
- @Test
- void both() throws UnirestException {
- final String baseUrl = pair.url();
-
- final com.mashape.unirest.http.HttpResponse res =
- Unirest.post(baseUrl + "/both")
- .field("a", "aval")
- .field("b", "bval")
- .field("one", helloFile)
- .asString();
-
- assertThat(res.getBody()).isEqualTo("nm:one fn:hello.txt size:" + helloFile.length() + " paramMap:{a=[aval], b=[bval]}");
- }
-
- @Test
- void multipleFiles() throws UnirestException {
- final String baseUrl = pair.url();
-
- final com.mashape.unirest.http.HttpResponse res =
- Unirest.post(baseUrl + "/multi")
- .field("a", "a1")
- .field("a", "a2")
- .field("b", "b1")
- .field("b", "b2")
- .field("c", "c1")
- .field("one", helloFile)
- .field("one", hello2File)
- .asString();
-
- assertThat(res.getBody()).isEqualTo("file[nm:one fn:hello.txt size:" + helloFile.length()+ "]file[nm:one fn:hello2.txt size:" + hello2File.length() + "] paramMap:{a=[a1, a2], b=[b1, b2], c=[c1]}");
- }
-
- @Test
- void multipleFilesAll() throws UnirestException {
- final String baseUrl = pair.url();
-
- final com.mashape.unirest.http.HttpResponse res =
- Unirest.post(baseUrl + "/multiAll")
- .field("one", helloFile)
- .field("two", hello2File)
- .asString();
-
- assertThat(res.getBody()).isEqualTo("file[nm:one fn:hello.txt size:" + helloFile.length()+ "]file[nm:two fn:hello2.txt size:" + hello2File.length() + "]");
- }
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/NestedRoutesTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/NestedRoutesTest.java
deleted file mode 100644
index d7858d97..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/NestedRoutesTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class NestedRoutesTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- Jex app = Jex.create()
- .routing(routing -> routing
- .get("/", ctx -> ctx.text("hello"))
- .path("api", () -> {
- routing.get(ctx -> ctx.text("apiRoot"));
- routing.get("{id}", ctx -> ctx.text("api-" + ctx.pathParam("id")));
- })
- .path("extra", () -> {
- routing.get(ctx -> ctx.text("extraRoot"));
- routing.get("{id}", ctx -> ctx.text("extra-id-" + ctx.pathParam("id")));
- routing.get("more/{id}", ctx -> ctx.text("extraMore-" + ctx.pathParam("id")));
- }));
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void get() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.body()).isEqualTo("hello");
- }
-
- @Test
- void get_api_paths() {
- var res = pair.request()
- .path("api").GET().asString();
-
- assertThat(res.body()).isEqualTo("apiRoot");
-
- res = pair.request()
- .path("api").path("99").GET().asString();
-
- assertThat(res.body()).isEqualTo("api-99");
- }
-
- @Test
- void get_extra_paths() {
- var res = pair.request()
- .path("extra").GET().asString();
-
- assertThat(res.body()).isEqualTo("extraRoot");
-
- res = pair.request()
- .path("extra").path("99").GET().asString();
-
- assertThat(res.body()).isEqualTo("extra-id-99");
-
- res = pair.request()
- .path("extra").path("more").path("42").GET().asString();
-
- assertThat(res.body()).isEqualTo("extraMore-42");
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/Roles.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/Roles.java
deleted file mode 100644
index 87dd02e0..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/Roles.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.avaje.jex.base;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-/**
- * Create an app specific Role annotation that uses the
- * app specific role enum.
- */
-@Target(value={METHOD, TYPE})
-@Retention(value=RUNTIME)
-public @interface Roles {
-
- /**
- * Specify the permitted roles (using app specific enum).
- */
- AppRoles[] value() default {};
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RolesTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RolesTest.java
deleted file mode 100644
index 111092bc..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RolesTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import io.avaje.jex.Role;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class RolesTest {
-
- enum AppRoles implements Role {
- ADMIN,
- USER,
- }
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .accessManager((handler, ctx, permittedRoles) -> {
- final String role = ctx.queryParam("role");
- if (role == null || !permittedRoles.contains(AppRoles.valueOf(role))) {
- ctx.status(401).text("Unauthorized");
- } else {
- ctx.attribute("authBy", role);
- handler.handle(ctx);
- }
- })
- .routing(routing -> routing
- .get(ctx -> ctx.text("get"))
- .get("/multi", ctx -> ctx.text("multi-" + ctx.attribute("authBy"))).withRoles(AppRoles.ADMIN, AppRoles.USER)
- .get("/user", ctx -> ctx.text("user")).withRoles(AppRoles.USER)
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void noRoles() {
- HttpResponse res = pair.request().GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("get");
- }
-
- @Test
- void singleRole_withRole() {
- HttpResponse res = pair.request()
- .path("user").queryParam("role", "USER")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("user");
- }
-
- @Test
- void singleRole_withoutRole() {
- HttpResponse res = pair.request()
- .path("user")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(401);
- assertThat(res.body()).isEqualTo("Unauthorized");
- }
-
- @Test
- void multiRole_withRole() {
- HttpResponse res = pair.request()
- .path("multi").queryParam("role", "USER")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("multi-USER");
- }
-
- @Test
- void multiRole_withRole2() {
- HttpResponse res = pair.request()
- .path("multi").queryParam("role", "ADMIN")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("multi-ADMIN");
- }
-
- @Test
- void multiRole_withoutRole() {
- HttpResponse res = pair.request()
- .path("multi")
- .GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(401);
- assertThat(res.body()).isEqualTo("Unauthorized");
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteRegexTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteRegexTest.java
deleted file mode 100644
index bd00befa..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteRegexTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class RouteRegexTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .get("/foo/{id:[0-9]+}", ctx -> ctx.text("digit:" + ctx.pathParam("id")))
- .get("/foo/count", ctx -> ctx.text("count"))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void when_digitMatch() {
- HttpResponse res = pair.request().path("foo/7").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("digit:7");
- }
-
- @Test
- void when_notDigitMatch() {
- HttpResponse res = pair.request().path("foo/count").GET().asString();
-
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("count");
- }
-
- @Test
- void when_noMatch() {
- HttpResponse res = pair.request().path("foo/a").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(404);
- }
-
-}
diff --git a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteSplatTest.java b/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteSplatTest.java
deleted file mode 100644
index 41aae324..00000000
--- a/avaje-jex-jetty/src/test/java/io/avaje/jex/base/RouteSplatTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.avaje.jex.base;
-
-import io.avaje.jex.Jex;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.Test;
-
-import java.net.http.HttpResponse;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-class RouteSplatTest {
-
- static TestPair pair = init();
-
- static TestPair init() {
- var app = Jex.create()
- .routing(routing -> routing
- .get("/{id}/one", ctx -> ctx.text("id:" + ctx.pathParam("id")))
- .get("/{id}/one2", ctx -> ctx.text("id:" + ctx.pathParam("id")))
- .get("//one", ctx -> ctx.text("s1:" + ctx.pathParam("a")))
- .get("//two/", ctx -> ctx.text("s2:" + ctx.pathParam("a") + "|" + ctx.pathParam("b")))
- );
- return TestPair.create(app);
- }
-
- @AfterAll
- static void end() {
- pair.shutdown();
- }
-
- @Test
- void when_utf8Encoded() {
- // This fails in Jetty 11.0.2 due to: https://github.com/eclipse/jetty.project/issues/6001
- // String path = URLEncoder.encode("java/kotlin", StandardCharsets.UTF_8)
- // + "/two/" + URLEncoder.encode("x/y", StandardCharsets.UTF_8);
- // HttpResponse res = pair.request().path(path).get().asString();
-
- HttpResponse res = pair.request().path("java/kotlin/two/x/y").GET().asString();
- assertThat(res.body()).isEqualTo("s2:java/kotlin|x/y");
- assertThat(res.statusCode()).isEqualTo(200);
- }
-
- @Test
- void when_pathParamMatch() {
- HttpResponse res = pair.request().path("42/one").GET().asString();
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("id:42");
- }
-
- @Test
- void when_splatMatch() {
- HttpResponse res = pair.request().path("42/foo/one").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("s1:42/foo");
- }
-
- @Test
- void when_splats() {
- HttpResponse res = pair.request().path("a/b/c/two/x/y").GET().asString();
-
- assertThat(res.statusCode()).isEqualTo(200);
- assertThat(res.body()).isEqualTo("s2:a/b/c|x/y");
- }
-
- @Test
- void when_noSplats() {
- HttpResponse