Skip to content

Handle Errors before After Handlers #170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 26, 2025
8 changes: 2 additions & 6 deletions avaje-jex/src/main/java/io/avaje/jex/HttpFilter.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.avaje.jex;

import java.io.IOException;

import com.sun.net.httpserver.HttpExchange;

/**
Expand Down Expand Up @@ -37,7 +35,7 @@ public interface HttpFilter {
* @param ctx the {@code Context} of the current request
* @param chain the {@code FilterChain} which allows the next filter to be invoked
*/
void filter(Context ctx, FilterChain chain) throws Exception;
void filter(Context ctx, FilterChain chain);

/**
* Filter chain that contains all subsequent filters that are configured, as well as the final
Expand All @@ -51,9 +49,7 @@ interface FilterChain {
* filter in the chain. The {@link HttpFilter} may decide to terminate the chain, by not calling
* this method. In this case, the filter <b>must</b> send the response to the request, because
* the application's {@linkplain HttpExchange exchange} handler will not be invoked.
*
* @throws IOException if an I/O error occurs
*/
void proceed() throws Exception;
void proceed();
}
}
27 changes: 17 additions & 10 deletions avaje-jex/src/main/java/io/avaje/jex/core/BaseFilterChain.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
package io.avaje.jex.core;

import java.util.List;
import java.util.ListIterator;
import java.util.Iterator;

import io.avaje.jex.ExchangeHandler;
import io.avaje.jex.HttpFilter;
import io.avaje.jex.HttpFilter.FilterChain;

final class BaseFilterChain implements FilterChain {

private final ListIterator<HttpFilter> iter;
private final Iterator<HttpFilter> filters;
private final ExchangeHandler handler;
private final JdkContext ctx;
private final ServiceManager mgr;

BaseFilterChain(List<HttpFilter> filters, ExchangeHandler handler, JdkContext ctx) {
this.iter = filters.listIterator();
BaseFilterChain(Iterator<HttpFilter> filters, ExchangeHandler handler, JdkContext ctx, ServiceManager mgr) {
this.filters = filters;
this.handler = handler;
this.ctx = ctx;
this.mgr = mgr;
}

@Override
public void proceed() throws Exception {
if (!iter.hasNext()) {
handler.handle(ctx);
ctx.setMode(Mode.AFTER);
public void proceed() {
if (filters.hasNext()) {
filters.next().filter(ctx, this);
} else {
iter.next().filter(ctx, this);
try {
if (!ctx.responseSent()) {
handler.handle(ctx);
}
} catch (Exception t) {
mgr.handleException(ctx, t);
}
}
ctx.setMode(Mode.AFTER);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ final class ExceptionManager {
}

@SuppressWarnings("unchecked")
<T extends Exception> ExceptionHandler<Exception> find(Class<T> exceptionType) {
ExceptionHandler<Exception> find(Class<?> exceptionType) {
Class<?> type = exceptionType;
do {
final ExceptionHandler<?> handler = handlers.get(type);
final var handler = handlers.get(type);
if (handler != null) {
return (ExceptionHandler<Exception>) handler;
}
Expand All @@ -36,7 +36,7 @@ <T extends Exception> ExceptionHandler<Exception> find(Class<T> exceptionType) {
}

void handle(JdkContext ctx, Exception e) {
final ExceptionHandler<Exception> handler = find(e.getClass());
final var handler = find(e.getClass());
if (handler != null) {
try {
handler.handle(ctx, e);
Expand Down
11 changes: 3 additions & 8 deletions avaje-jex/src/main/java/io/avaje/jex/core/RoutingHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.sun.net.httpserver.HttpHandler;

import io.avaje.jex.HttpFilter;
import io.avaje.jex.compression.CompressionConfig;
import io.avaje.jex.http.NotFoundException;
import io.avaje.jex.routes.SpiRoutes;

Expand Down Expand Up @@ -37,7 +36,7 @@ public void handle(HttpExchange exchange) {

if (route == null) {
var ctx = new JdkContext(mgr, exchange, uri, Set.of());
handleException(
mgr.handleException(
ctx,
new NotFoundException(
"No route matching http method %s, with path %s".formatted(routeType.name(), uri)));
Expand All @@ -48,10 +47,10 @@ public void handle(HttpExchange exchange) {
JdkContext ctx = new JdkContext(mgr, exchange, route.matchPath(), params, route.roles());
try {
ctx.setMode(Mode.BEFORE);
new BaseFilterChain(filters, route.handler(), ctx).proceed();
new BaseFilterChain(filters.iterator(), route.handler(), ctx, mgr).proceed();
handleNoResponse(exchange);
} catch (Exception e) {
handleException(ctx, e);
mgr.handleException(ctx, e);
}
} finally {
route.dec();
Expand All @@ -65,8 +64,4 @@ private void handleNoResponse(HttpExchange exchange) throws IOException {
exchange.sendResponseHeaders(204, -1);
}
}

private void handleException(JdkContext ctx, Exception e) {
mgr.handleException(ctx, e);
}
}
4 changes: 2 additions & 2 deletions avaje-jex/src/main/java/io/avaje/jex/core/ServiceManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ Routing.Type lookupRoutingType(String method) {
}
}

void handleException(JdkContext ctx, Exception e) {
exceptionHandler.handle(ctx, e);
void handleException(JdkContext ctx, Exception t) {
exceptionHandler.handle(ctx, t);
}

void render(Context ctx, String name, Map<String, Object> model) {
Expand Down
Loading