0

I'm running Quarkus 2.7.0.CR1 with this code:

 return httpRequest.sendBuffer(createBuffer())
                   .onSubscription()
                       .invoke(() -> metricsRecorder.start(METRICS_NAME))
                   .onFailure()
                       .recoverWithUni(failure -> fetchWithOtherCredentials())
                   ...

onFailure() triggers if port in URL is not responding at all. But when returning HTTP 500 from WireMock this code just throws WebApplicationException with status 500 without triggering onFailure(). This is the exception that triggers onFailure():

io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8085

AnnotatedConnectException seems to be checked exception but in this example IllegalArgumentException is used which is RuntimeException like WebApplicationException.

I thought onFailure() should trigger on any exception. Any ideas what is going on? I have tested with @QuarkusTest and also by running Quarkus locally with mvn compile quarkus:dev.

4

1 回答 1

3

HttpRequest.sendBuffer() returns a Uni<HttpResponse<T>>. When the server responds with status 500, the Web Client does not emit a failure, it emits an HttpResponse with status code 500.

You should inspect the response, like this:

Uni<HttpResponse> uni = httpRequest
    .sendBuffer(createBuffer())
    .onItem().transformToUni(res -> {
        if (res.statusCode() == 200 && res.getHeader("content-type").equals("application/json")) {
          // Do something with JSON body and return new Uni
        } else {
          // Generate failure as Uni
        }
    });

Another option is to use response predicates:

Uni<HttpResponse> uni = httpRequest
    .expect(ResponsePredicate.SC_SUCCESS)
    .expect(ResponsePredicate.JSON)
    .sendBuffer(createBuffer());

In this case, the returned Uni<HttpResponse> is successful only when the response has status code 200 and a JSON body, otherwise it is failed.

于 2022-02-01T10:01:39.670 回答