Skip to content

Commit cd2be95

Browse files
authored
Merge pull request #45085 from geoand/#45058
Use Content-Type header from PreMatching filter during media type negotiation
2 parents b6a42ad + 85e99ff commit cd2be95

File tree

2 files changed

+127
-5
lines changed

2 files changed

+127
-5
lines changed

independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/MediaTypeMapper.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,11 @@ public MediaTypeMapper(List<RuntimeResource> runtimeResources) {
5858

5959
@Override
6060
public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
61-
String contentType = requestContext.serverRequest().getRequestHeader(HttpHeaders.CONTENT_TYPE);
62-
// if there's no Content-Type it's */*
63-
MediaType contentMediaType = contentType != null ? MediaType.valueOf(contentType) : MediaType.WILDCARD_TYPE;
6461
// find the best matching consumes type. Note that the arguments are reversed from their definition
6562
// of desired/provided, but we do want the result to be a media type we consume, since that's how we key
6663
// our methods, rather than the single media type we get from the client. This way we ensure we get the
6764
// best match.
68-
MediaType consumes = MediaTypeHelper.getBestMatch(Collections.singletonList(contentMediaType),
69-
consumesTypes);
65+
MediaType consumes = MediaTypeHelper.getBestMatch(contentTypeFromRequest(requestContext), consumesTypes);
7066
Holder selectedHolder = resourcesByConsumes.get(consumes);
7167
// if we haven't found anything, try selecting the wildcard type, if any
7268
if (selectedHolder == null) {
@@ -97,6 +93,18 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti
9793
requestContext.restart(selectedResource);
9894
}
9995

96+
private List<MediaType> contentTypeFromRequest(ResteasyReactiveRequestContext requestContext) {
97+
List<String> contentTypeList = requestContext.getHttpHeaders().getRequestHeader(HttpHeaders.CONTENT_TYPE);
98+
if (contentTypeList.isEmpty()) {
99+
return Collections.singletonList(MediaType.WILDCARD_TYPE);
100+
}
101+
List<MediaType> result = new ArrayList<>(contentTypeList.size());
102+
for (String s : contentTypeList) {
103+
result.add(MediaType.valueOf(s));
104+
}
105+
return result;
106+
}
107+
100108
public MediaType selectMediaType(ResteasyReactiveRequestContext requestContext, Holder holder) {
101109
MediaType selected = null;
102110
List<String> accepts = requestContext.getHttpHeaders().getRequestHeader(HttpHeaders.ACCEPT);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package org.jboss.resteasy.reactive.server.vertx.test.matching;
2+
3+
import static io.restassured.RestAssured.given;
4+
import static org.hamcrest.CoreMatchers.is;
5+
6+
import java.io.IOException;
7+
import java.util.function.Supplier;
8+
9+
import jakarta.ws.rs.Consumes;
10+
import jakarta.ws.rs.POST;
11+
import jakarta.ws.rs.Path;
12+
import jakarta.ws.rs.container.ContainerRequestContext;
13+
import jakarta.ws.rs.container.ContainerRequestFilter;
14+
import jakarta.ws.rs.container.PreMatching;
15+
import jakarta.ws.rs.core.MediaType;
16+
import jakarta.ws.rs.ext.Provider;
17+
18+
import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest;
19+
import org.jboss.shrinkwrap.api.ShrinkWrap;
20+
import org.jboss.shrinkwrap.api.spec.JavaArchive;
21+
import org.junit.jupiter.api.Test;
22+
import org.junit.jupiter.api.extension.RegisterExtension;
23+
24+
public class PreMatchContentTypeInHeaderTest {
25+
26+
@RegisterExtension
27+
static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest()
28+
.setArchiveProducer(new Supplier<>() {
29+
@Override
30+
public JavaArchive get() {
31+
return ShrinkWrap.create(JavaArchive.class);
32+
}
33+
});
34+
35+
@Test
36+
public void filterNotSettingContentType() {
37+
given()
38+
.header("Content-Type", "application/json")
39+
.body("[]")
40+
.when()
41+
.post("/test")
42+
.then()
43+
.statusCode(200)
44+
.body(is("json-[]"));
45+
46+
given()
47+
.header("Content-Type", "text/plain")
48+
.body("input")
49+
.when()
50+
.post("/test")
51+
.then()
52+
.statusCode(200)
53+
.body(is("text-input"));
54+
}
55+
56+
@Test
57+
public void filterSettingContentTypeToText() {
58+
given()
59+
.header("Content-Type", "application/json")
60+
.header("test-content-type", "text/plain")
61+
.body("[]")
62+
.when()
63+
.post("/test")
64+
.then()
65+
.statusCode(200)
66+
.body(is("text-[]"));
67+
}
68+
69+
@Test
70+
public void filterSettingContentTypeToJson() {
71+
given()
72+
.header("Content-Type", "text/plain")
73+
.header("test-content-type", "application/json")
74+
.body("input")
75+
.when()
76+
.post("/test")
77+
.then()
78+
.statusCode(200)
79+
.body(is("json-input"));
80+
}
81+
82+
@Path("test")
83+
public static class TestResource {
84+
85+
@POST
86+
@Consumes(MediaType.TEXT_PLAIN)
87+
public String fromText(String input) {
88+
return "text-" + input;
89+
}
90+
91+
@POST
92+
@Consumes(MediaType.APPLICATION_JSON)
93+
public String fromJson(String input) {
94+
return "json-" + input;
95+
}
96+
}
97+
98+
public record Result(String message) {
99+
100+
}
101+
102+
@Provider
103+
@PreMatching
104+
public static class Filter implements ContainerRequestFilter {
105+
106+
@Override
107+
public void filter(ContainerRequestContext context) throws IOException {
108+
String testContentType = context.getHeaderString("test-content-type");
109+
if (testContentType != null) {
110+
context.getHeaders().putSingle("Content-Type", testContentType);
111+
}
112+
}
113+
}
114+
}

0 commit comments

Comments
 (0)