From 8faee8f0d79c8f9cecd37391139add6b8c3650be Mon Sep 17 00:00:00 2001 From: "Stefan Vitz (C804185)" Date: Thu, 6 Jun 2024 10:36:55 +0200 Subject: [PATCH] fix: Response.charset does not support RFC 7231 compliant Content-Type headers using quotation marks as application/json; charset="utf-8" --- core/src/main/java/feign/Response.java | 22 ++++++++++++++-------- core/src/test/java/feign/ResponseTest.java | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/feign/Response.java b/core/src/main/java/feign/Response.java index 62f1b655e..855680f98 100644 --- a/core/src/main/java/feign/Response.java +++ b/core/src/main/java/feign/Response.java @@ -158,8 +158,8 @@ public int status() { /** * Nullable and not set when using http/2 - * - * See https://github.com/http2/http2-spec/issues/202 + * See ... + * See ... */ public String reason() { return reason; @@ -195,6 +195,11 @@ public ProtocolVersion protocolVersion() { return protocolVersion; } + /** + * Returns a charset object based on the requests content type. Defaults to UTF-8 + * See rfc7231 - Accept-Charset + * See rfc7231 - Media Type + */ public Charset charset() { Collection contentTypeHeaders = headers().get("Content-Type"); @@ -205,7 +210,8 @@ public Charset charset() { if (contentTypeParmeters.length > 1) { String[] charsetParts = contentTypeParmeters[1].split("="); if (charsetParts.length == 2 && "charset".equalsIgnoreCase(charsetParts[0].trim())) { - return Charset.forName(charsetParts[1]); + String charsetString = charsetParts[1].replaceAll("\"", ""); + return Charset.forName(charsetString); } } } @@ -314,7 +320,7 @@ public Reader asReader() { } @Override - public Reader asReader(Charset charset) throws IOException { + public Reader asReader(Charset charset) { checkNotNull(charset, "charset should not be null"); return new InputStreamReader(inputStream, charset); } @@ -360,24 +366,24 @@ public boolean isRepeatable() { } @Override - public InputStream asInputStream() throws IOException { + public InputStream asInputStream() { return new ByteArrayInputStream(data); } @SuppressWarnings("deprecation") @Override - public Reader asReader() throws IOException { + public Reader asReader() { return new InputStreamReader(asInputStream(), UTF_8); } @Override - public Reader asReader(Charset charset) throws IOException { + public Reader asReader(Charset charset) { checkNotNull(charset, "charset should not be null"); return new InputStreamReader(asInputStream(), charset); } @Override - public void close() throws IOException {} + public void close() {} } diff --git a/core/src/test/java/feign/ResponseTest.java b/core/src/test/java/feign/ResponseTest.java index eea7e95cd..7ba39c175 100644 --- a/core/src/test/java/feign/ResponseTest.java +++ b/core/src/test/java/feign/ResponseTest.java @@ -14,6 +14,8 @@ package feign; import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -59,6 +61,20 @@ void canAccessHeadersCaseInsensitively() { }); } + @Test + void charsetSupportsMediaTypesWithQuotedCharset() { + Map> headersMap = new LinkedHashMap<>(); + List valueList = Collections.singletonList("application/json; charset=\"utf-8\""); + headersMap.put("Content-Type", valueList); + Response response = Response.builder() + .status(200) + .headers(headersMap) + .request(Request.create(HttpMethod.GET, "/api", Collections.emptyMap(), null, Util.UTF_8)) + .body(new byte[0]) + .build(); + assertThat(response.charset()).isEqualTo(Util.UTF_8); + } + @Test void headerValuesWithSameNameOnlyVaryingInCaseAreMerged() { Map> headersMap = new LinkedHashMap<>();