Skip to content

Commit

Permalink
Use charset from response Content-Type header to decode (#1302)
Browse files Browse the repository at this point in the history
* If charset is set in Content-type, we decode response using that charset

* Java 8 compatibility

* Format fix

* Moving code to get charset to Response in order to be used by another
decoders
  • Loading branch information
jaime-pineiro-imatia committed Feb 3, 2021
1 parent 4cf1a54 commit b79d6fc
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 5 deletions.
19 changes: 19 additions & 0 deletions core/src/main/java/feign/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,25 @@ public Request request() {
return request;
}

public Charset charset() {

Collection<String> contentTypeHeaders = headers().get("Content-Type");

if (contentTypeHeaders != null) {
for (String contentTypeHeader : contentTypeHeaders) {
String[] contentTypeParmeters = contentTypeHeader.split(";");
if (contentTypeParmeters.length > 1) {
String[] charsetParts = contentTypeParmeters[1].split("=");
if (charsetParts.length == 2 && "charset".equalsIgnoreCase(charsetParts[0].trim())) {
return Charset.forName(charsetParts[1]);
}
}
}
}

return Util.UTF_8;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder("HTTP/1.1 ").append(status);
Expand Down
13 changes: 8 additions & 5 deletions jackson/src/main/java/feign/jackson/JacksonDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@
*/
package feign.jackson;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.RuntimeJsonMappingException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.RuntimeJsonMappingException;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;
Expand All @@ -47,7 +49,7 @@ public JacksonDecoder(ObjectMapper mapper) {
public Object decode(Response response, Type type) throws IOException {
if (response.body() == null)
return null;
Reader reader = response.body().asReader(Util.UTF_8);
Reader reader = response.body().asReader(response.charset());
if (!reader.markSupported()) {
reader = new BufferedReader(reader, 1);
}
Expand All @@ -66,4 +68,5 @@ public Object decode(Response response, Type type) throws IOException {
throw e;
}
}

}
26 changes: 26 additions & 0 deletions jackson/src/test/java/feign/jackson/JacksonCodecTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@
import org.junit.Test;
import java.io.Closeable;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
Expand Down Expand Up @@ -169,6 +172,29 @@ public void customEncoder() {
+ "} ]");
}

@Test
public void decoderCharset() throws IOException {
Zone zone = new Zone("denominator.io.", "ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ");

Map<String, Collection<String>> headers = new HashMap<String, Collection<String>>();
headers.put("Content-Type", Arrays.asList("application/json;charset=ISO-8859-1"));

Response response = Response.builder()
.status(200)
.reason("OK")
.request(Request.create(HttpMethod.GET, "/api", Collections.emptyMap(), null, Util.UTF_8))
.headers(headers)
.body(new String("" //
+ "{" + System.lineSeparator()
+ " \"name\" : \"DENOMINATOR.IO.\"," + System.lineSeparator()
+ " \"id\" : \"ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ\"" + System.lineSeparator()
+ "}").getBytes(StandardCharsets.ISO_8859_1))
.build();
assertEquals(zone.get("id"),
((Zone) new JacksonDecoder().decode(response, new TypeReference<Zone>() {}.getType()))
.get("id"));
}

@Test
public void decodesIterator() throws Exception {
List<Zone> zones = new LinkedList<Zone>();
Expand Down

0 comments on commit b79d6fc

Please sign in to comment.