Skip to content

Commit

Permalink
Add uncaught error handler
Browse files Browse the repository at this point in the history
  • Loading branch information
code-brazier committed Dec 23, 2024
1 parent 1cd9a5c commit c64cab5
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
12 changes: 12 additions & 0 deletions vertx-web/src/main/java/io/vertx/ext/web/Router.java
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,18 @@ static Router router(Vertx vertx) {
@Fluent
Router errorHandler(int statusCode, Handler<RoutingContext> errorHandler);

/**
* Specify an handler to handle an error for any status code that doesn't have a specific handler assigned.
* The handler will be called when the context fails and other failure handlers didn't write the reply or when an exception is thrown inside an handler.
* You <b>must not</b> use {@link RoutingContext#next()} inside the error handler
* This does not affect the normal failure routing logic.
*
* @param errorHandler error handler. Note: You <b>must not</b> use {@link RoutingContext#next()} inside the provided handler
* @return a reference to this, so the API can be used fluently
*/
@Fluent
Router uncaughtErrorHandler(Handler<RoutingContext> errorHandler);

/**
* Used to route a context to the router. Used for sub-routers. You wouldn't normally call this method directly.
*
Expand Down
6 changes: 6 additions & 0 deletions vertx-web/src/main/java/io/vertx/ext/web/impl/RouterImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ public synchronized Router errorHandler(int statusCode, Handler<RoutingContext>
return this;
}

@Override
public synchronized Router uncaughtErrorHandler(Handler<RoutingContext> errorHandler) {
state = state.setUncaughtErrorHandler(errorHandler);
return this;
}

synchronized void add(RouteImpl route) {
state = state.addRoute(route);
// notify the listeners as the routes are changed
Expand Down
35 changes: 32 additions & 3 deletions vertx-web/src/main/java/io/vertx/ext/web/impl/RouterState.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ final class RouterState {
private final TreeSet<RouteImpl> routes;
private final int orderSequence;
private final Map<Integer, Handler<RoutingContext>> errorHandlers;
private final Handler<RoutingContext> uncaughtErrorHandler;
private final Handler<Router> modifiedHandler;
private final AllowForwardHeaders allowForward;
private final Map<String, Object> metadata;

public RouterState(RouterImpl router, TreeSet<RouteImpl> routes, int orderSequence, Map<Integer, Handler<RoutingContext>> errorHandlers, Handler<Router> modifiedHandler, AllowForwardHeaders allowForward, Map<String, Object> metadata) {
public RouterState(RouterImpl router, TreeSet<RouteImpl> routes, int orderSequence, Map<Integer, Handler<RoutingContext>> errorHandlers, final Handler<RoutingContext> uncaughtErrorHandler, Handler<Router> modifiedHandler, AllowForwardHeaders allowForward, Map<String, Object> metadata) {
this.router = router;
this.routes = routes;
this.orderSequence = orderSequence;
this.errorHandlers = errorHandlers;
this.uncaughtErrorHandler = uncaughtErrorHandler;
this.modifiedHandler = modifiedHandler;
this.allowForward = allowForward;
this.metadata = metadata;
Expand All @@ -78,6 +80,7 @@ public RouterState(RouterImpl router) {
0,
null,
null,
null,
AllowForwardHeaders.NONE,
null);
}
Expand All @@ -99,6 +102,7 @@ RouterState setRoutes(Set<RouteImpl> routes) {
new TreeSet<>(routeComparator),
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -119,6 +123,7 @@ RouterState addRoute(RouteImpl route) {
routes,
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -130,6 +135,7 @@ RouterState clearRoutes() {
new TreeSet<>(routeComparator),
this.orderSequence,
this.errorHandlers,
null,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -147,6 +153,7 @@ RouterState removeRoute(RouteImpl route) {
routes,
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -162,6 +169,7 @@ RouterState incrementOrderSequence() {
this.routes,
this.orderSequence + 1,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -173,6 +181,7 @@ RouterState setOrderSequence(int orderSequence) {
this.routes,
orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -188,16 +197,20 @@ RouterState setErrorHandlers(Map<Integer, Handler<RoutingContext>> errorHandlers
this.routes,
this.orderSequence,
errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
}

Handler<RoutingContext> getErrorHandler(int errorCode) {
if (errorHandlers != null) {
return errorHandlers.get(errorCode);
final Handler<RoutingContext> errorHandler = errorHandlers.get(errorCode);
if (errorHandler != null) {
return errorHandler;
}
}
return null;
return uncaughtErrorHandler;
}

RouterState putErrorHandler(int errorCode, Handler<RoutingContext> errorHandler) {
Expand All @@ -206,6 +219,7 @@ RouterState putErrorHandler(int errorCode, Handler<RoutingContext> errorHandler)
this.routes,
this.orderSequence,
this.errorHandlers == null ? new HashMap<>() : new HashMap<>(errorHandlers),
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -214,6 +228,18 @@ RouterState putErrorHandler(int errorCode, Handler<RoutingContext> errorHandler)
return newState;
}

RouterState setUncaughtErrorHandler(Handler<RoutingContext> errorHandler) {
return new RouterState(
this.router,
this.routes,
this.orderSequence,
this.errorHandlers,
errorHandler,
this.modifiedHandler,
this.allowForward,
this.metadata);
}

public Handler<Router> getModifiedHandler() {
return modifiedHandler;
}
Expand All @@ -224,6 +250,7 @@ public RouterState setModifiedHandler(Handler<Router> modifiedHandler) {
this.routes,
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
modifiedHandler,
this.allowForward,
this.metadata);
Expand All @@ -235,6 +262,7 @@ public RouterState setAllowForward(AllowForwardHeaders allow) {
this.routes,
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
allow,
this.metadata);
Expand All @@ -256,6 +284,7 @@ public RouterState putMetadata(String key, Object value) {
this.routes,
this.orderSequence,
this.errorHandlers,
this.uncaughtErrorHandler,
this.modifiedHandler,
this.allowForward,
Collections.unmodifiableMap(metadata));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3693,6 +3693,14 @@ public void testExtractCallee() throws Exception {
200, "OK");
}

@Test
public void testUncaughtErrorHandler() throws Exception {
router.route().consumes("text/html").handler(rc -> rc.response().end());
router.uncaughtErrorHandler(context -> context.response().setStatusCode(context.statusCode()).setStatusMessage("Dumb").end());

testRequestWithContentType(HttpMethod.GET, "/foo", "something/html", 415, "Dumb");
}

@Test
public void testErrorHandlerInvokedOnce() throws Exception {
AtomicInteger errorHandlerInvocations = new AtomicInteger();
Expand Down

0 comments on commit c64cab5

Please sign in to comment.