Skip to content

Commit

Permalink
Harmonize the usage of charset in the Content-Type headers for RESTEa…
Browse files Browse the repository at this point in the history
…sy Reactive

The idea is that we know only append it for specific response media types.
Before this change, the charset was added depending on how the return type
of the Resource method

Relates to: #25295
  • Loading branch information
geoand committed May 5, 2022
1 parent ebfa3f0 commit 50c9b9b
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void testApplicationJsonMediaType() {
Response response = base.request().get();
Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
String body = response.readEntity(String.class);
Assertions.assertEquals(response.getHeaderString("Content-Type"), "application/json");
Assertions.assertEquals(response.getHeaderString("Content-Type"), "application/json;charset=UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jboss.resteasy.reactive.server.core;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.reactive.server.spi.ContentType;

Expand All @@ -9,12 +11,33 @@
*/
public class EncodedMediaType implements ContentType {
final MediaType mediaType;
final String charset;
String encoded;
String charset;

public EncodedMediaType(MediaType mediaType) {
this.mediaType = mediaType;
this.charset = mediaType.getParameters().get("charset");
MediaType effectiveMediaType = mediaType;
String effectiveCharset;
String originalCharset = mediaType.getParameters().get("charset");
if (isStringMediaType(mediaType)) {
effectiveCharset = originalCharset;
if (effectiveCharset == null) {
effectiveCharset = StandardCharsets.UTF_8.name();
}
} else {
// it doesn't make sense to add charset to non string types
effectiveCharset = null;
}
this.charset = effectiveCharset;
if (!Objects.equals(originalCharset, effectiveCharset)) {
effectiveMediaType = mediaType.withCharset(effectiveCharset);
}
this.mediaType = effectiveMediaType;
}

// TODO: does this need to be more complex?
private boolean isStringMediaType(MediaType mediaType) {
return mediaType.getType().equals("application")
|| (mediaType.getType().equals("text") && mediaType.getSubtype().equals("plain"));
}

@Override
Expand All @@ -37,9 +60,6 @@ public String getEncoded() {

@Override
public String getCharset() {
if (charset == null) {
return charset = mediaType.getParameters().get("charset");
}
return charset;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ public void write(ResteasyReactiveRequestContext context, Object entity) throws
serverSerializersMediaType = selectedMediaType;
context.setResponseContentType(selectedMediaType);
// this will be used as the fallback if Response does NOT contain a type
context.serverResponse().addResponseHeader(HttpHeaders.CONTENT_TYPE, selectedMediaType.toString());
context.serverResponse().addResponseHeader(HttpHeaders.CONTENT_TYPE,
context.getResponseContentType().toString());
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package org.jboss.resteasy.reactive.server.vertx.test.mediatype;

import static io.restassured.RestAssured.when;
import static org.junit.jupiter.api.Assertions.*;

import java.nio.charset.StandardCharsets;
import java.util.function.Supplier;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import org.jboss.resteasy.reactive.server.vertx.test.framework.ResteasyReactiveUnitTest;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class CharsetTest {

@RegisterExtension
static ResteasyReactiveUnitTest test = new ResteasyReactiveUnitTest()
.setArchiveProducer(new Supplier<>() {
@Override
public JavaArchive get() {
return ShrinkWrap.create(JavaArchive.class)
.addClasses(TestResource.class);
}
});

@Test
public void testText() {
String contentType = when().get("/test/text")
.then()
.statusCode(200)
.extract().header("Content-Type");
assertEquals("text/plain;charset=UTF-8", contentType);
}

@Test
public void testResponseText() {
String contentType = when().get("/test/response/text")
.then()
.statusCode(200)
.extract().header("Content-Type");
assertEquals("text/plain;charset=UTF-8", contentType);
}

@Test
public void testJson() {
String contentType = when().get("/test/json")
.then()
.statusCode(200)
.extract().header("Content-Type");
assertEquals("application/json;charset=UTF-8", contentType);
}

@Test
public void testImage() {
String contentType = when().get("/test/image")
.then()
.statusCode(200)
.extract().header("Content-Type");
assertEquals("image/png", contentType);
}

@Path("test")
public static class TestResource {

@Path("text")
@Produces("text/plain")
@GET
public String textPlain() {
return "text";
}

@Path("response/text")
@Produces("text/plain")
@GET
public Response responseTextPlain() {
return Response.ok("text").build();
}

@Path("json")
@Produces("application/json")
@GET
public String json() {
return "{\"foo\": \"bar\"}";
}

@Path("response/json")
@Produces("application/json")
@GET
public Response responseJson() {
return Response.ok("{\"foo\": \"bar\"}").build();
}

@Path("image")
@Produces("image/png")
@GET
public Response imagePng() {
return Response.ok("fake image".getBytes(StandardCharsets.UTF_8)).build();
}

@Path("response/image")
@Produces("image/png")
@GET
public byte[] responseImagePng() {
return "fake image".getBytes(StandardCharsets.UTF_8);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public void testApplicationJsonMediaType() {
Response response = base.request().get();
Assertions.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
String body = response.readEntity(String.class);
Assertions.assertEquals(response.getHeaderString("Content-Type"), "application/json");
Assertions.assertEquals(response.getHeaderString("Content-Type"), "application/json;charset=UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down

0 comments on commit 50c9b9b

Please sign in to comment.