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

SSE RESTEasy Reactive if an error occurs, cannot retrieve the body #38325

Closed
xtof974 opened this issue Jan 22, 2024 · 13 comments · Fixed by #38369
Closed

SSE RESTEasy Reactive if an error occurs, cannot retrieve the body #38325

xtof974 opened this issue Jan 22, 2024 · 13 comments · Fixed by #38369
Labels
area/rest kind/question Further information is requested
Milestone

Comments

@xtof974
Copy link

xtof974 commented Jan 22, 2024

Describe the bug

My Quarkus application is a client that calls a Server-Sent Event (SSE) endpoint. I followed the recommendations of the documentation specific to SSE. It works as long as there is no error.
If an error occured, RESTEasy Reactive throws a WebApplicationException. I have register an exceptionMapper and a ClientExceptionMapper to catch the Response object. It works but I have to read the body of the error response 400 to do specific stuffs
Unfortunately, the entity or streamEntity return allways null.

How manage this kind of usecase ?

Expected behavior

a way to retrieve the body error

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

No response

Quarkus version or git rev

3.6.6

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

No response

Additional information

No response

@xtof974 xtof974 added the kind/bug Something isn't working label Jan 22, 2024
Copy link

quarkus-bot bot commented Jan 22, 2024

/cc @FroMage (resteasy-reactive), @geoand (resteasy-reactive), @stuartwdouglas (resteasy-reactive)

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

What version of Quarkus are you using?

@geoand geoand added the triage/needs-feedback We are waiting for feedback. label Jan 22, 2024
@xtof974
Copy link
Author

xtof974 commented Jan 22, 2024

@geoand I'm using the version 3.6.6

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

Thanks.

Can you share what approxitely the data looks like and what class you trying to deserialize it to?

I am just trying to get a more complete understanding of the problem you are facing.

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

In case you are tying to use SSE for consuming the OpenAI APIs, you are in luck - have a loot at our langchain4j extension which already provides all you need.

If you really want to see how things have been implemented on the SSE side, check out this.

@xtof974
Copy link
Author

xtof974 commented Jan 22, 2024

I have a service A that calls a service B that calls the SSE endpoint via the interface C. The way below.
The interface C returns Multi to the service B that returns it to service A. The latter transforms it to Multi. I specify again that all this works well (without error > 400 return by interface C)

service A :

Multi<ChatMessagesSseResponse> chatMessageResponse = this.proxyChatMessageResource.callChat(chatMessageRequest)
              .onItem()
              .transform(res -> {
                  ChatMessagesSseResponse chatMessagesSseResponse = new ChatMessagesSseResponse();
                  try {
                      if (!res.contains("[DONE]")) {
                          ChatMessagesAzureSseResponse chatMessagesResponse = objectMapper.readValue(res, ChatMessagesAzureSseResponse.class);
                          if (chatMessagesResponse.choices().get(0).delta().content() != null && chatMessagesResponse.id() != null) {
                              chatMessagesSseResponse = new ChatMessagesSseResponse(chatMessagesResponse);
                          }
                      }
                  } catch (JsonProcessingException e) {
                      throw new RuntimeException(e);
                  }
                  return chatMessagesSseResponse;
              })
              .onFailure().invoke(t ->
                      logger.info(String.format("Oh no! We received a failure: %s",
                              t.getMessage())));
      return chatMessageResponse
              .select().where(message -> message.getId() != null);
}

service B :

@RestClient
   AzureOpenAiApi apiAzure;

   public Multi<String> callChat(ChatMessagesAzureRequest chatMessageRequest) {
       logger.info("callChat External API");
           return this.apiAzure.processGenerativeAIWithChatMessageSse(this.apiKey,
                   this.deploymentId,
                   this.apiVersion,
                   chatMessageRequest)
                   .onFailure().invoke(t ->
                   logger.info(String.format("Oh no! We received a failure: %s",
                           t.getMessage()))
           );
   }

interface C :

@RegisterRestClient(configKey = "azure-api")
@RegisterProvider(WebApplicationExceptionRequestFilter.class)
@RegisterProvider(ResponseContainerRequestFilter.class)

@Path("/openai/deployments")
public interface AzureOpenAiApi {

    @POST
    @Path("/{deploymentId}/chat/completions")
    @RestStreamElementType(MediaType.APPLICATION_JSON)
    Multi<String> processGenerativeAIWithChatMessageSse(@HeaderParam("api-key") String apiKey,
                                                                              @PathParam("deploymentId") String deploymentId,
                                                                              @QueryParam("api-version") String apiVersion,
                                                                              ChatMessagesAzureRequest chatMessagesAzureRequest);

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

See my comment above :).

Moreoever, the missing piece from your code is likely this.

@geoand geoand closed this as completed Jan 22, 2024
@geoand geoand added kind/question Further information is requested and removed kind/bug Something isn't working triage/needs-feedback We are waiting for feedback. labels Jan 22, 2024
@xtof974
Copy link
Author

xtof974 commented Jan 22, 2024

Hi, thanks for example of code @geoand
I study it but the implementation does not solve the problem. Indeed, I have a ClientExceptionMapper like the example provided but the response entity (body) is blank when an error occurs see the screenshot below.

  1. all works fine if the openAi api return 200 with data
  2. when response from openAi > 400, impossible to obtain the body of that response
    image

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

What does the body of an HTTP 400 look like?

@xtof974
Copy link
Author

xtof974 commented Jan 22, 2024

{
    "error": {
        "message": "The response was filtered due to the prompt triggering Azure OpenAI's content management policy. Please modify your prompt and retry. To learn more about our content filtering policies please read our documentation: https://go.microsoft.com/fwlink/?linkid=2198766",
        "type": null,
        "param": "prompt",
        "code": "content_filter",
        "status": 400
    }
}

@geoand
Copy link
Contributor

geoand commented Jan 22, 2024

I'll have a look some time this week

@xtof974
Copy link
Author

xtof974 commented Jan 22, 2024

I have to identify what kind of error it is. I precise that I can't read the body only on SSE error, with classic API response I can , unfortunately it is not my usecase :-(.

Thx for your feedback @geoand

@geoand
Copy link
Contributor

geoand commented Jan 24, 2024

#38369 fixes the problem

geoand added a commit that referenced this issue Jan 24, 2024
Ensure that response body of unsuccessful SSE request can be read
@quarkus-bot quarkus-bot bot added this to the 3.9 - main milestone Jan 24, 2024
@gsmet gsmet modified the milestones: 3.9 - main, 3.6.8 Jan 24, 2024
gsmet pushed a commit to gsmet/quarkus that referenced this issue Jan 24, 2024
gsmet pushed a commit to gsmet/quarkus that referenced this issue Jan 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants