Skip to content

Commit

Permalink
fix: Response.charset does not support RFC 7231 compliant Content-Typ…
Browse files Browse the repository at this point in the history
…e headers using quotation marks as application/json; charset="utf-8"
  • Loading branch information
Stefan Vitz (C804185) committed Jun 6, 2024
1 parent 0cfb0ea commit 8faee8f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 8 deletions.
22 changes: 14 additions & 8 deletions core/src/main/java/feign/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href="https://github.com/http2/http2-spec/issues/202">...</a>
* See <a href="https://github.com/http2/http2-spec/issues/202">...</a>
*/
public String reason() {
return reason;
Expand Down Expand Up @@ -195,6 +195,11 @@ public ProtocolVersion protocolVersion() {
return protocolVersion;
}

/**
* Returns a charset object based on the requests content type. Defaults to UTF-8
* See <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.3">rfc7231 - Accept-Charset</a>
* See <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.1">rfc7231 - Media Type</a>
*/
public Charset charset() {

Collection<String> contentTypeHeaders = headers().get("Content-Type");
Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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() {}

}

Expand Down
16 changes: 16 additions & 0 deletions core/src/test/java/feign/ResponseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -59,6 +61,20 @@ void canAccessHeadersCaseInsensitively() {
});
}

@Test
void charsetSupportsMediaTypesWithQuotedCharset() {
Map<String, Collection<String>> headersMap = new LinkedHashMap<>();
List<String> 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<String, Collection<String>> headersMap = new LinkedHashMap<>();
Expand Down

0 comments on commit 8faee8f

Please sign in to comment.