Skip to content
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

Sanitize RESTEasy Reactive exception logging #31975

Merged
merged 1 commit into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package io.quarkus.resteasy.reactive.server.runtime;

import java.io.IOException;
import java.io.UncheckedIOException;

import jakarta.ws.rs.core.SecurityContext;

import org.jboss.resteasy.reactive.server.core.Deployment;
import org.jboss.resteasy.reactive.server.handlers.InvocationHandler;
import org.jboss.resteasy.reactive.server.handlers.ResourceRequestFilterHandler;
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
import org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext;
import org.jboss.resteasy.reactive.spi.ThreadSetupAction;
Expand Down Expand Up @@ -57,8 +62,30 @@ protected SecurityContext createSecurityContext() {

@Override
protected void handleUnrecoverableError(Throwable throwable) {
context.fail(throwable);
super.handleUnrecoverableError(throwable);
context.fail(effectiveThrowableForQuarkusLogging(throwable)); // this results in io.quarkus.vertx.http.runtime.QuarkusErrorHandler logging the error
endResponse(); // we just want to end the response, nothing more
}

// this is a massive hack to get QuarkusErrorHandler to log an IOException when it comes from user code
private Throwable effectiveThrowableForQuarkusLogging(Throwable throwable) {
if (!(throwable instanceof IOException)) {
return throwable;
}
StackTraceElement[] stackTrace = throwable.getStackTrace();
int depth = 0;
boolean convertException = false;
while ((depth < stackTrace.length) && (depth < 5)) { // only check a few of the top frames
StackTraceElement stackTraceElement = stackTrace[depth];
String className = stackTraceElement.getClassName();
if (className.contains(InvocationHandler.class.getSimpleName()) || className.contains(
ResourceRequestFilterHandler.class.getSimpleName())) { // TODO: we may need more here
convertException = true;
break;
}
depth++;
}
return convertException ? new UncheckedIOException((IOException) throwable) : throwable;

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,10 @@ public ResteasyReactiveRequestContext setWriterInterceptors(WriterInterceptor[]

protected void handleUnrecoverableError(Throwable throwable) {
log.error("Request failed", throwable);
endResponse();
}

protected void endResponse() {
if (serverResponse().headWritten()) {
serverRequest().closeConnection();
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public RuntimeExceptionMapper(ExceptionMapping mapping, ClassLoader classLoader)
@SuppressWarnings({ "unchecked", "rawtypes" })
public void mapException(Throwable throwable, ResteasyReactiveRequestContext context) {
Class<?> klass = throwable.getClass();
//we don't thread WebApplicationException's thrown from the client as true 'WebApplicationException'
//we don't read WebApplicationException's thrown from the client as true 'WebApplicationException'
//we consider it a security risk to transparently pass on the result to the calling server
boolean isWebApplicationException = throwable instanceof WebApplicationException
&& !(throwable instanceof ResteasyReactiveClientProblem);
Expand Down Expand Up @@ -101,7 +101,7 @@ public void mapException(Throwable throwable, ResteasyReactiveRequestContext con
}
if (isWebApplicationException) {
context.setResult(response);
logBlockingErrorIfRequired(throwable, context);
log.debug("Application failed the request", throwable);
return;
}
if (throwable instanceof IOException) {
Expand Down