Proper error response when handing unexpected errors

Closes #10176
This commit is contained in:
Pedro Igor 2022-02-14 19:39:13 -03:00
parent bbe9ab38bc
commit a9668d14ce
2 changed files with 46 additions and 7 deletions

View File

@ -25,6 +25,9 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakTransactionManager;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
@ -64,7 +67,7 @@ public class QuarkusRequestFilter implements Handler<RoutingContext> {
try {
tx.begin();
context.next();
promise.complete();
promise.tryComplete();
} catch (Throwable cause) {
promise.fail(cause);
// re-throw so that the any exception is handled from parent
@ -90,6 +93,10 @@ public class QuarkusRequestFilter implements Handler<RoutingContext> {
close(session);
} catch (Throwable cause) {
promise.fail(cause);
context.response().headers().clear();
context.response().putHeader(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN);
context.response().putHeader(HttpHeaderNames.CONTENT_LENGTH, "0");
context.response().setStatusCode(HttpResponseStatus.INTERNAL_SERVER_ERROR.code());
}
});
}
@ -105,14 +112,18 @@ public class QuarkusRequestFilter implements Handler<RoutingContext> {
protected void close(KeycloakSession session) {
KeycloakTransactionManager tx = session.getTransactionManager();
if (tx.isActive()) {
if (tx.getRollbackOnly()) {
tx.rollback();
} else {
tx.commit();
try {
if (tx.isActive()) {
if (tx.getRollbackOnly()) {
tx.rollback();
} else {
tx.commit();
}
}
} finally {
session.close();
}
session.close();
}
private ClientConnection createClientConnection(HttpServerRequest request) {

View File

@ -172,6 +172,34 @@ public class ComponentsTest extends AbstractAdminTest {
assertEquals("fixed-id", id);
}
@Test
public void failCreateWithLongName() {
StringBuilder name = new StringBuilder();
while (name.length() < 30) {
name.append("invalid");
}
ComponentRepresentation rep = createComponentRepresentation(name.toString());
rep.getConfig().addFirst("required", "foo");
ComponentsResource components = realm.components();
try (Response response = components.add(rep)) {
if (Response.Status.INTERNAL_SERVER_ERROR.getStatusCode() == response.getStatus()) {
// using database should fail due to constraint violations
assertFalse(components.query().stream().map(ComponentRepresentation::getName).anyMatch(name.toString()::equals));
} else if (Response.Status.CREATED.getStatusCode() == response.getStatus()) {
// using the map storage should work because there are no constraints
String id = ApiUtil.getCreatedId(response);
assertNotNull(components.component(id).toRepresentation());
} else {
fail("Unexpected response");
}
}
}
@Test
public void testUpdate() {
ComponentRepresentation rep = createComponentRepresentation("mycomponent");