You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Discovered in 4.3.8, but I can see it in master too.
Context
When a request path is empty or does not start with /, RoutingContext fails in its constructor:
if (path == null || path.length() == 0) {
// HTTP paths must start with a '/'
fail(400);
} else if (path.charAt(0) != '/') {
// For compatiblity we return `Not Found` when a path does not start with `/`
fail(404);
}
This will trigger failure handler assigned to this route immediately. However this constructor is called in RouterImpl like this:
new RoutingContextImpl(null, this, request, state.getRoutes()).next();
What this means that the order of actions is such:
Routing context constructor
1. Call fail() and failed() now returns true
2. doFail() causes iterateNext
3. Error handler is found
4. Error handler is executed
Constructor was completed
Back in RouterImpl, next() is called on constructed RoutingContextImpl
Because routing context iterated already, it cannot find the error handler
"Unhandled exception in router" appears in the log
Do you have a reproducer?
Try this:
final Router router = Router.router(vertx);
router.get("/*")
.handler(routingContext -> {
routingContext.response().setStatusCode(200);
routingContext.end("Hello world!");
})
.failureHandler(routingContext->{
int statusCode = routingContext.statusCode();
final var failure = routingContext.failure();
final var request = routingContext.request();
if(failure != null) {
if(failure instanceof HttpException) {
statusCode = ((HttpException)failure).getStatusCode();
LOGGER.info("Handling HttpException at path {} code {}", request.path(), statusCode);
}
else {
statusCode = 500;
LOGGER.warn("Handling unexpected exception at path {}", request.path(), statusCode);
}
}
else if(statusCode == -1) {
statusCode = 500;
LOGGER.warn("status code was -1 at path {}", request.path(), statusCode);
}
else {
LOGGER.info("Handling error code without exception at path {} code {}", request.path(), statusCode);
}
try {
routingContext.end("error message here")
.onFailure((e)->{
LOGGER.error("cannot send error for path {}", request.path());
e.printStackTrace();
})
.onSuccess((unused)->{
LOGGER.info("sent error for path {}", request.path());
});
}
catch(Exception justSoYouKnowItDoesNotThrow) {
LOGGER.error("cannot call end()", justSoYouKnowItDoesNotThrow);
}
});
return vertx
.createHttpServer(new HttpServerOptions().setHandle100ContinueAutomatically(true).setTcpKeepAlive(true))
.requestHandler(router)
.listen(port, host)
.onSuccess(res -> LOGGER.info("Listening on {}:{}", host, port))
.onFailure(
cause
-> LOGGER.warn("Cannot listen on {}:{} error: {}", host, port, cause.toString()));
I can see this in my log if I make a request:
INFO HttpServer Handling error code without exception at path blablabla code 404
ERROR RoutingContext Unhandled exception in router
INFO HttpServer sent error for path blablabla
To make the request, I just used raw python socket and sent this:
Version
Discovered in 4.3.8, but I can see it in master too.
Context
When a request path is empty or does not start with
/
,RoutingContext
fails in its constructor:This will trigger failure handler assigned to this route immediately. However this constructor is called in
RouterImpl
like this:What this means that the order of actions is such:
1. Call
fail()
andfailed()
now returns true2. doFail() causes
iterateNext
3. Error handler is found
4. Error handler is executed
RouterImpl
,next()
is called on constructedRoutingContextImpl
"Unhandled exception in router"
appears in the logDo you have a reproducer?
Try this:
I can see this in my log if I make a request:
To make the request, I just used raw python socket and sent this:
The text was updated successfully, but these errors were encountered: