quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.53k stars 2.61k forks source link

When using reactive restclient in 2.8.2.Final with Response, getEntity() returns null even if there is a body in Response #25496

Closed flygarej closed 1 week ago

flygarej commented 2 years ago

Describe the bug

In 2.7.2 using the old restclient and a call with signature

@Path("/response")
@GET
Uni<Response> getResponse();

so I could do some work with headers before touching the entity data. Old code then would ask for an InputStream using response.getEntity() which worked fine.

Reactive restclient will return null in the same situation. I can get the body by doing String data=response.readEntity(String.class) however so there is an entity.

Expected behavior

When restclient returns Uni and there is proper data in the Response, response.getEntity() should return an InputStream.

Actual behavior

In Quarkus 2.8.2, when calling response.getEntity(), null is returned, indicating that the response does not have an entity.

How to Reproduce?

Steps: 1: Compile and start backing web service "restservice", runs on localhost port 8080 2: Compile and start service that uses 2.8.2.Final reactive restclient "restclient", runs on localhost port 8088 3: Compile and run service that uses 2.7.2.Final nonreactive restclient, runs on localhost port 8098 4: Trigger either rest client by using curl http://localhost:8088/hello/response or curl http://localhost:8098/hello/response

You'll get a canned response from the call, but in the restclient service logs you'll see the differing behaviour of getEntity() restclient_response_reproduced.zip .

Output of uname -a or ver

Linux deadpool 5.13.0-40-generic #45~20.04.1-Ubuntu SMP Mon Apr 4 09:38:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "18.0.1" 2022-04-19 OpenJDK Runtime Environment Zulu18.30+11-CA (build 18.0.1+10) OpenJDK 64-Bit Server VM Zulu18.30+11-CA (build 18.0.1+10, mixed mode, sharing)

GraalVM version (if different from Java)

N/A

Quarkus version or git rev

2.8.2

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)

Additional information

No response

quarkus-bot[bot] commented 2 years ago

/cc @michalszynkiewicz

brunobastosg commented 1 year ago

I got the same error using Quarkus 2.14.3.Final

lucasmelz commented 1 year ago

Facing the same issue here... I opened a question on stack overflow about it: https://stackoverflow.com/questions/76100343/how-to-properly-chain-calls-to-external-apis-using-mutiny-and-process-the-respo

lucasmelz commented 1 year ago

What happened with me was that the response was actually somehow available inside the callback, since I could print its headers and the status code, and also the endpoint would give me back the full response, but I couldn't access (or print) the body of the response inside the callback... It happens when you have an Uni\<Response> object. My way around it was to work with Uni\<String> instead of Uni\<Response> and since I could handle exceptions just by looking at the body of the responses, I could use this approach (I don't need the status code or the headers). Anyway this was kind of a hack... If any Mutiny developer is reading this, please take a look at this bug.

cescoffier commented 1 year ago

Note that HTTP is made in a way that the headers are received first and the body possibly later (and then trailers, if any). So, having the headers does not mean the body has been received yet.

\CC @Sgitario

autumnfound commented 1 month ago

This still occurs in Quarkus 3.8.5 (current LTS), a current reproducer available at https://github.com/autumnfound/quarkus-25496-reproducer. If you cast the response and use the entity stream or have a direct type to cast to, you can get around the error, but then have to manually handle streaming unicode characters and list support can get sticky in casting cases.

gastaldi commented 1 week ago

There is a consequence of this behavior in #41887, which makes Response.fromResponse broken because it copies the getEntity and not the entityStream