Skip to content

Commit c65d8b7

Browse files
Use charset from response Content-Type header to decode (OpenFeign#1302)
* 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
1 parent 4f67a6c commit c65d8b7

3 files changed

Lines changed: 55 additions & 2 deletions

File tree

core/src/main/java/feign/Response.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,25 @@ public Request request() {
182182
return request;
183183
}
184184

185+
public Charset charset() {
186+
187+
Collection<String> contentTypeHeaders = headers().get("Content-Type");
188+
189+
if (contentTypeHeaders != null) {
190+
for (String contentTypeHeader : contentTypeHeaders) {
191+
String[] contentTypeParmeters = contentTypeHeader.split(";");
192+
if (contentTypeParmeters.length > 1) {
193+
String[] charsetParts = contentTypeParmeters[1].split("=");
194+
if (charsetParts.length == 2 && "charset".equalsIgnoreCase(charsetParts[0].trim())) {
195+
return Charset.forName(charsetParts[1]);
196+
}
197+
}
198+
}
199+
}
200+
201+
return Util.UTF_8;
202+
}
203+
185204
@Override
186205
public String toString() {
187206
StringBuilder builder = new StringBuilder("HTTP/1.1 ").append(status);

jackson/src/main/java/feign/jackson/JacksonDecoder.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import com.fasterxml.jackson.databind.ObjectMapper;
1919
import com.fasterxml.jackson.databind.RuntimeJsonMappingException;
2020
import feign.Response;
21-
import feign.Util;
2221
import feign.codec.Decoder;
2322
import java.io.BufferedReader;
2423
import java.io.IOException;
@@ -48,7 +47,7 @@ public JacksonDecoder(ObjectMapper mapper) {
4847
@Override
4948
public Object decode(Response response, Type type) throws IOException {
5049
if (response.body() == null) return null;
51-
Reader reader = response.body().asReader(Util.UTF_8);
50+
Reader reader = response.body().asReader(response.charset());
5251
if (!reader.markSupported()) {
5352
reader = new BufferedReader(reader, 1);
5453
}

jackson/src/test/java/feign/jackson/JacksonCodecTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,12 @@
3535
import feign.Util;
3636
import java.io.Closeable;
3737
import java.io.IOException;
38+
import java.nio.charset.StandardCharsets;
3839
import java.util.ArrayList;
3940
import java.util.Arrays;
41+
import java.util.Collection;
4042
import java.util.Collections;
43+
import java.util.HashMap;
4144
import java.util.Iterator;
4245
import java.util.LinkedHashMap;
4346
import java.util.LinkedList;
@@ -205,6 +208,38 @@ public void customEncoder() {
205208
+ "} ]");
206209
}
207210

211+
@Test
212+
public void decoderCharset() throws IOException {
213+
Zone zone = new Zone("denominator.io.", "ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ");
214+
215+
Map<String, Collection<String>> headers = new HashMap<String, Collection<String>>();
216+
headers.put("Content-Type", Arrays.asList("application/json;charset=ISO-8859-1"));
217+
218+
Response response =
219+
Response.builder()
220+
.status(200)
221+
.reason("OK")
222+
.request(
223+
Request.create(HttpMethod.GET, "/api", Collections.emptyMap(), null, Util.UTF_8))
224+
.headers(headers)
225+
.body(
226+
new String(
227+
"" //
228+
+ "{"
229+
+ System.lineSeparator()
230+
+ " \"name\" : \"DENOMINATOR.IO.\","
231+
+ System.lineSeparator()
232+
+ " \"id\" : \"ÁÉÍÓÚÀÈÌÒÙÄËÏÖÜÑ\""
233+
+ System.lineSeparator()
234+
+ "}")
235+
.getBytes(StandardCharsets.ISO_8859_1))
236+
.build();
237+
assertEquals(
238+
zone.get("id"),
239+
((Zone) new JacksonDecoder().decode(response, new TypeReference<Zone>() {}.getType()))
240+
.get("id"));
241+
}
242+
208243
@Test
209244
public void decodesIterator() throws Exception {
210245
List<Zone> zones = new LinkedList<Zone>();

0 commit comments

Comments
 (0)