Skip to content

Commit

Permalink
Take response status of aborted request into account in JAX-RS Client
Browse files Browse the repository at this point in the history
Fixes: quarkusio#22827
(cherry picked from commit c511555)
  • Loading branch information
geoand authored and gsmet committed Jan 15, 2022
1 parent 993ff61 commit 6e130d1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.jaxrs.client.reactive.deployment.test;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.net.URL;

import javax.enterprise.event.Observes;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.vertx.core.Handler;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;

public class ClientRequestFilterAbortWithTestCase {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(Endpoint.class));

@TestHTTPResource
URL url;

private Client client;

@BeforeEach
public void before() {
client = ClientBuilder.newClient().register(TestClientRequestFilter.class);
}

@AfterEach
public void after() {
client.close();
}

@Test
public void test() {
Response response = client.target(url.toExternalForm() + "/hello").request().get();
assertEquals(999, response.getStatus());
}

public static class Endpoint {

public void setup(@Observes Router router) {
router.route("/hello").handler(new Handler<>() {
@Override
public void handle(RoutingContext event) {
event.response().setStatusCode(200).end();
}
});
}
}

@Provider
public static class TestClientRequestFilter implements ClientRequestFilter {

@Override
public void filter(ClientRequestContext requestContext) {
requestContext.abortWith(Response.status(999).build());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,36 @@ public class ClientSetResponseEntityRestHandler implements ClientRestHandler {

@Override
public void handle(RestClientRequestContext context) throws Exception {
ClientRequestContextImpl requestContext = context.getClientRequestContext();
ClientResponseContextImpl responseContext = new ClientResponseContextImpl(context);
if (context.isCheckSuccessfulFamily()) {
if (Response.Status.Family.familyOf(context.getResponseStatus()) != Response.Status.Family.SUCCESSFUL) {
throw new WebClientApplicationException(context.getResponseStatus(), context.getResponseReasonPhrase());
int effectiveResponseStatus = determineEffectiveResponseStatus(context, requestContext);
if (Response.Status.Family.familyOf(effectiveResponseStatus) != Response.Status.Family.SUCCESSFUL) {
throw new WebClientApplicationException(effectiveResponseStatus, context.getResponseReasonPhrase());
}
}
ClientRequestContextImpl requestContext = context.getClientRequestContext();

// the spec doesn't really say this, but the TCK checks that the abortWith entity ends up read
// so we have to write it, but without filters/interceptors
if (requestContext != null && requestContext.getAbortedWith() != null) {
if (isAbortedWith(requestContext)) {
setExistingEntity(requestContext.getAbortedWith(), responseContext, context);
}
}

private int determineEffectiveResponseStatus(RestClientRequestContext context, ClientRequestContextImpl requestContext) {
int effectiveResponseStatus = context.getResponseStatus();
if (effectiveResponseStatus == 0) {
if (isAbortedWith(requestContext)) {
effectiveResponseStatus = requestContext.getAbortedWith().getStatus();
}
}
return effectiveResponseStatus;
}

private boolean isAbortedWith(ClientRequestContextImpl requestContext) {
return requestContext != null && requestContext.getAbortedWith() != null;
}

private void setExistingEntity(Response abortedWith, ClientResponseContextImpl responseContext,
RestClientRequestContext restClientRequestContext) throws IOException {
Object value = abortedWith.getEntity();
Expand Down

0 comments on commit 6e130d1

Please sign in to comment.