diff --git a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java index 94bf2c9f..2cf07e2f 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java +++ b/avaje-jex/src/main/java/io/avaje/jex/DefaultRouting.java @@ -7,6 +7,7 @@ import java.util.Deque; import java.util.List; import java.util.Set; +import java.util.function.Consumer; import io.avaje.jex.security.Role; @@ -179,7 +180,6 @@ public Routing filter(HttpFilter handler) { return this; } - private static class Entry implements Routing.Entry { private final Type type; diff --git a/avaje-jex/src/main/java/io/avaje/jex/FilterChain.java b/avaje-jex/src/main/java/io/avaje/jex/FilterChain.java index b5966196..033f6aaf 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/FilterChain.java +++ b/avaje-jex/src/main/java/io/avaje/jex/FilterChain.java @@ -8,7 +8,7 @@ public interface FilterChain { /** - * Calls the next filter in the chain, or else the users exchange handler, if this is the final + * Calls the next filter in the chain, or else the user's exchange handler, if this is the final * filter in the chain. The {@link HttpFilter} may decide to terminate the chain, by not * calling this method. In this case, the filter must send the response to the request, * because the application's {@linkplain HttpExchange exchange} handler will not be invoked. diff --git a/avaje-jex/src/main/java/io/avaje/jex/Handler.java b/avaje-jex/src/main/java/io/avaje/jex/Handler.java index e23816d2..aacbf15f 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Handler.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Handler.java @@ -1,7 +1,18 @@ package io.avaje.jex; +/** + * A handler which is invoked to process HTTP exchanges. Each HTTP exchange is handled by one of + * these handlers. + */ @FunctionalInterface public interface Handler { + /** + * Handle the given request and generate an appropriate response. See {@link Context} for a + * description of the steps involved in handling an exchange. + * + * @param ctx the request context containing the request from the client and used to send the + * response + */ void handle(Context ctx); } diff --git a/avaje-jex/src/main/java/io/avaje/jex/Routing.java b/avaje-jex/src/main/java/io/avaje/jex/Routing.java index c2096e8f..c36022f6 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/Routing.java +++ b/avaje-jex/src/main/java/io/avaje/jex/Routing.java @@ -3,6 +3,7 @@ import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.function.Consumer; import io.avaje.jex.security.Role; @@ -128,6 +129,26 @@ public interface Routing { */ Routing filter(HttpFilter handler); + /** Add a preprocessing filter for all requests. */ + default Routing before(Consumer handler) { + + return filter( + (ctx, chain) -> { + handler.accept(ctx); + chain.proceed(); + }); + } + + /** Add a post-processing filter for all requests. */ + default Routing after(Consumer handler) { + + return filter( + (ctx, chain) -> { + chain.proceed(); + handler.accept(ctx); + }); + } + /** * Return all the registered handlers. */ diff --git a/avaje-jex/src/main/java/io/avaje/jex/jdk/RoutingFilter.java b/avaje-jex/src/main/java/io/avaje/jex/jdk/RoutingFilter.java index f78fdbdd..32ecb31d 100644 --- a/avaje-jex/src/main/java/io/avaje/jex/jdk/RoutingFilter.java +++ b/avaje-jex/src/main/java/io/avaje/jex/jdk/RoutingFilter.java @@ -46,6 +46,7 @@ public void doFilter(HttpExchange exchange, Filter.Chain chain) { handleException(ctx, e); } finally { routes.dec(); + exchange.close(); } } else { route.inc(); @@ -63,6 +64,7 @@ public void doFilter(HttpExchange exchange, Filter.Chain chain) { } } finally { route.dec(); + exchange.close(); } } } diff --git a/avaje-jex/src/test/java/io/avaje/jex/jdk/FilterTest.java b/avaje-jex/src/test/java/io/avaje/jex/jdk/FilterTest.java index 7d9e4b03..a40afe17 100644 --- a/avaje-jex/src/test/java/io/avaje/jex/jdk/FilterTest.java +++ b/avaje-jex/src/test/java/io/avaje/jex/jdk/FilterTest.java @@ -26,11 +26,7 @@ static TestPair init() { .get("/one", ctx -> ctx.text("one")) .get("/two", ctx -> ctx.text("two")) .get("/two/{id}", ctx -> ctx.text("two-id")) - .filter( - (ctx, chain) -> { - ctx.header("before-all", "set"); - chain.proceed(); - }) + .before(ctx -> ctx.header("before-all", "set")) .filter( (ctx, chain) -> { if (ctx.url().contains("/two/")) { @@ -38,11 +34,7 @@ static TestPair init() { } chain.proceed(); }) - .filter( - (ctx, chain) -> { - chain.proceed(); - afterAll.set("set"); - }) + .after(ctx -> afterAll.set("set")) .filter( (ctx, chain) -> { chain.proceed();