Feign declarative call service feign.codec.DecodeException: Error while extracting response for type [class **] and…

A few days ago, when I was working on a project, I encountered a garbled return from the feign call, which caused a program error. The reason is that the dependency version of cloud is too low, and feign does not support gzip decoding. Without upgrading the jar, a filter was added.

 

code show as below:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class FeignResponseDecoder implements Decoder {
private final Decoder delegate;
public FeignResponseDecoder(Decoder delegate) {
Objects.requireNonNull(delegate, "Decoder must not be null. ");
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException {
Collection<String> values = response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER);
if (Objects.nonNull(values) && !values.isEmpty() && values.contains(HttpEncoding.GZIP_ENCODING)) {
byte[] compressed = Util.toByteArray(response.body().asInputStream());
if ((compressed == null) || (compressed.length == 0)) {
return delegate.decode(response, type);
}
//decompression part
//after decompress we are delegating the decompressed response to default
//decoder
if (isCompressed(compressed)) {
final StringBuilder output = new StringBuilder();
final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed));
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
String line;
while ((line = bufferedReader.readLine()) != null) {
output.append(line);
}
Response uncompressedResponse = response.toBuilder().body(output.toString().getBytes()).build();
return delegate.decode(uncompressedResponse, type);
} else {
return delegate.decode(response, type);
}
} else {
return delegate.decode(response, type);
}
}
private static boolean isCompressed(final byte[] compressed) {
return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
}
}
public class FeignResponseDecoder implements Decoder { private final Decoder delegate; public FeignResponseDecoder(Decoder delegate) { Objects.requireNonNull(delegate, "Decoder must not be null. "); this.delegate = delegate; } @Override public Object decode(Response response, Type type) throws IOException { Collection<String> values = response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER); if (Objects.nonNull(values) && !values.isEmpty() && values.contains(HttpEncoding.GZIP_ENCODING)) { byte[] compressed = Util.toByteArray(response.body().asInputStream()); if ((compressed == null) || (compressed.length == 0)) { return delegate.decode(response, type); } //decompression part //after decompress we are delegating the decompressed response to default //decoder if (isCompressed(compressed)) { final StringBuilder output = new StringBuilder(); final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed)); final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8)); String line; while ((line = bufferedReader.readLine()) != null) { output.append(line); } Response uncompressedResponse = response.toBuilder().body(output.toString().getBytes()).build(); return delegate.decode(uncompressedResponse, type); } else { return delegate.decode(response, type); } } else { return delegate.decode(response, type); } } private static boolean isCompressed(final byte[] compressed) { return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8)); } }
public class FeignResponseDecoder implements Decoder {
    private final Decoder delegate;
 
    public FeignResponseDecoder(Decoder delegate) {
        Objects.requireNonNull(delegate, "Decoder must not be null. ");
        this.delegate = delegate;
    }
 
    @Override
    public Object decode(Response response, Type type) throws IOException {
        Collection<String> values = response.headers().get(HttpEncoding.CONTENT_ENCODING_HEADER);
        if (Objects.nonNull(values) && !values.isEmpty() && values.contains(HttpEncoding.GZIP_ENCODING)) {
            byte[] compressed = Util.toByteArray(response.body().asInputStream());
            if ((compressed == null) || (compressed.length == 0)) {
                return delegate.decode(response, type);
            }
            //decompression part
            //after decompress we are delegating the decompressed response to default
            //decoder
            if (isCompressed(compressed)) {
                final StringBuilder output = new StringBuilder();
                final GZIPInputStream gis = new GZIPInputStream(new ByteArrayInputStream(compressed));
                final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    output.append(line);
                }
                Response uncompressedResponse = response.toBuilder().body(output.toString().getBytes()).build();
                return delegate.decode(uncompressedResponse, type);
            } else {
                return delegate.decode(response, type);
            }
        } else {
            return delegate.decode(response, type);
        }
    }
 
    private static boolean isCompressed(final byte[] compressed) {
        return (compressed[0] == (byte) (GZIPInputStream.GZIP_MAGIC)) && (compressed[1] == (byte) (GZIPInputStream.GZIP_MAGIC >> 8));
    }
}

 

Then inject this class as a bean:

@Bean
public Decoder GZIPResponseDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
    Decoder decoder = new FeignResponseDecoder(new SpringDecoder(messageConverters));
    return decoder;
}

Read More:

Leave a Reply

Your email address will not be published. Required fields are marked *