Skip to content

HeaderHelper.getMediaType throws ClassCastException when Content-Type header is stored as a List #47507

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

Open
calvernaz opened this issue Apr 23, 2025 · 8 comments · May be fixed by #47546
Open
Labels
area/rest kind/bug Something isn't working triage/needs-reproducer We are waiting for a reproducer.

Comments

@calvernaz
Copy link

Describe the bug

Using the resteasy-client to fetch a binary file "svg" i'm getting a ClassCastException.

Request:

curl '/public/gms-logo.svg'

The exception:

java.lang.ClassCastException: class java.util.Arrays$ArrayList
  cannot be cast to class jakarta.ws.rs.core.MediaType
	at org.jboss.resteasy.util.HeaderHelper.getMediaType(HeaderHelper.java:115)
Image

Expected behavior

Return the excepted content media type.

Actual behavior

Throws an exception.

How to Reproduce?

A client like this:

public interface WebAppProxyClient {

  @GET
  @Path("/public/{path: .*}")
  Uni<Response> staticResourceRequest(@PathParam("path") String path);
}
}

Output of uname -a or ver

No response

Output of java -version

No response

Quarkus version or git rev

No response

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

No response

Additional information

No response

@calvernaz calvernaz added the kind/bug Something isn't working label Apr 23, 2025
@gsmet
Copy link
Member

gsmet commented Apr 23, 2025

Any chance you could prepare a small Maven reproducer?

It looks legit but it's the kind of thing we can struggle to reproduce.

Thanks!

Copy link

quarkus-bot bot commented Apr 23, 2025

/cc @FroMage (rest), @geoand (rest)

@gsmet
Copy link
Member

gsmet commented Apr 24, 2025

Somehow, something is wrapping what should be a single content type into a List and this is what you see.

That being said, there's something odd because HeaderHelper is a RESTEasy Classic class and shouldn't be used if you are using RESTEasy Reactive.

I think we really need a small reproducer to be able to check what's going on.

@gsmet gsmet added the triage/needs-reproducer We are waiting for a reproducer. label Apr 24, 2025
@calvernaz
Copy link
Author

calvernaz commented Apr 24, 2025

@gsmet

Apologies in advance my reproducers are never the most simple, but I think this one is easy to run.

Decompress the folder and run the start.sh script.

  • This will start the nodejs server that serves the SVG file.
  • It starts quarkus running a jax-rs handler and has a quarkus rest client calling the nodejs server.

Once the servers are up, takes couple of seconds hit the endpoint using the following:

curl -vvv localhost:8080/public/gms-logo.svg

Expect an exception like the one mentioned in the issue above.

bug.zip

@gsmet
Copy link
Member

gsmet commented Apr 24, 2025

OK, so you can workaround it by being a bit more careful when copying the headers and iterate on them if a list is returned but I kinda agree we should do better on our side.

Working on a PR.

@calvernaz
Copy link
Author

OK, so you can workaround it by being a bit more careful when copying the headers and iterate on them if a list is returned but I kinda agree we should do better on our side.

Working on a PR.

The reproducer has that header iteration, but the problem happens before. That iteration was just an experiment I was trying out related to yet another issue.

gsmet added a commit to gsmet/quarkus that referenced this issue Apr 25, 2025
The JAX-RS API is very loose and allows adding Object and in some cases
we actually add a List to the headers and we need to take this into
account.

While I'm usually not for handling things this way, the API is not
enforcing things properly so I think we really need to handle this
ourself.

Fixes quarkusio#47507
@gsmet gsmet linked a pull request Apr 25, 2025 that will close this issue
@gsmet
Copy link
Member

gsmet commented Apr 25, 2025

The reproducer has that header iteration, but the problem happens before. That iteration was just an experiment I was trying out related to yet another issue.

So from what I can see, if I drop the header transformation from your reproducer, things are working fine, even without my patch.

So my PR is fixing the issue in the reproducer but I'm not sure it will fix the issue you have in your app, if you're under the impression it's not these lines failing. It might but I'm not sure.

Also there's something that is problematic in your issue description:

java.lang.ClassCastException: class java.util.Arrays$ArrayList
  cannot be cast to class jakarta.ws.rs.core.MediaType
	at org.jboss.resteasy.util.HeaderHelper.getMediaType(HeaderHelper.java:115)

org.jboss.resteasy.util.HeaderHelper is a class from RESTEasy Classic and AFAICS, you are using Quarkus REST/RESTEasy Reactive so I'm not entirely sure what's going on but it seems you have a mix of both.

I think you should try to understand what's going on there with your dependency tree.

On the positive side, I created a PR here: #47546 .

I would be interested in your feedback. Ideally if could build my PR and test things with your app, that would give us an indication as to if the issue is fixed for you.

https://github.com/quarkusio/quarkus/blob/main/CONTRIBUTING.md#checking-an-issue-is-fixed-in-main might help (except you have to build my PR code instead as long as it's not merged).

@calvernaz
Copy link
Author

The reproducer has that header iteration, but the problem happens before. That iteration was just an experiment I was trying out related to yet another issue.

So from what I can see, if I drop the header transformation from your reproducer, things are working fine, even without my patch.

That's correct, and to clear things out, removing the handling of the headers stops the exception to be thrown. What I meant is the code triggers the exception at a lower level.

So my PR is fixing the issue in the reproducer but I'm not sure it will fix the issue you have in your app, if you're under the impression it's not these lines failing. It might but I'm not sure.

Also there's something that is problematic in your issue description:

java.lang.ClassCastException: class java.util.Arrays$ArrayList
  cannot be cast to class jakarta.ws.rs.core.MediaType
	at org.jboss.resteasy.util.HeaderHelper.getMediaType(HeaderHelper.java:115)

org.jboss.resteasy.util.HeaderHelper is a class from RESTEasy Classic and AFAICS, you are using Quarkus REST/RESTEasy Reactive so I'm not entirely sure what's going on but it seems you have a mix of both.

I think you should try to understand what's going on there with your dependency tree.

Again you are right here, I've cleanup the dependencies and without the headers handling I don't get the original issue (not disclosed) and the exception.

On the positive side, I created a PR here: #47546 .

I would be interested in your feedback. Ideally if could build my PR and test things with your app, that would give us an indication as to if the issue is fixed for you.

I think if there was a need to handle the headers the issue would still be there, so I believe your PR still valid.

https://github.com/quarkusio/quarkus/blob/main/CONTRIBUTING.md#checking-an-issue-is-fixed-in-main might help (except you have to build my PR code instead as long as it's not merged).

Thanks for looking into this, it's really appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/bug Something isn't working triage/needs-reproducer We are waiting for a reproducer.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants