修改响应体改造2.2拦截器 [英] Modify response body retrofit 2.2 interceptor

查看:119
本文介绍了修改响应体改造2.2拦截器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Retrofit 2开发一个应用程序以请求API.该API位于ASP.NET中,并且使用GZip压缩并编码为Base64,如以下代码所示:

I'm developing an app using Retrofit 2 to request to API. This API is in ASP.NET and it is zipping with GZip and encoding to Base64, like the code below:

private static string Compress(string conteudo)
{
    Encoding encoding = Encoding.UTF8;
    byte[] raw = encoding.GetBytes(conteudo);

    using (var memory = new MemoryStream())
    {
        using (GZipStream gzip = new GZipStream(memory, CompressionMode.Compress, true))
        {
            gzip.Write(raw, 0, raw.Length);
        }
        return Convert.ToBase64String(memory.ToArray());
    }
}

private static string Decompress(string conteudo)
{
    Encoding encoding = Encoding.UTF8;
    var gzip = Convert.FromBase64String(conteudo);

    using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
    {
        int size = gzip.Length;
        byte[] buffer = new byte[size];
        using (MemoryStream memory = new MemoryStream())
        {
            int count = 0;
            do
            {
                count = stream.Read(buffer, 0, size);
                if (count > 0)
                {
                    memory.Write(buffer, 0, count);
                }
            }
            while (count > 0);
            return encoding.GetString(memory.ToArray());
        }
    }
}

现在,我需要在Android应用中执行Retrofit的响应,从Base64解码并解压缩.我尝试使用Interceptor进行此操作,但没有成功.

Now, what I need to do in my Android app is get the response from Retrofit, decode from Base64 and unzip it. I tried to do it using Interceptor, but I got no success.

这是我从服务H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA收到的返回值,对响应进行解码和解压缩,我们得到了true.

This is the return that I received from the service H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA, decoding and unzipping the response, we have true.

有人知道怎么做吗?

推荐答案

很简单.下面的代码使用Google Guava来解码Base64字符流,并使用Google Gson反序列化JSON内容.

It's easy. The code below uses Google Guava in order to decode Base64 character streams and Google Gson to deserialize JSON content.

考虑以下测试服务界面:

Consider the following test service interface:

interface IService {

    @GET("/")
    Call<String> get();

}

现在,您可以使用模板方法设计模式来实现拦截器响应输入流转换器库:

Now you can implement your interceptor response input stream transformer base using the template method design pattern:

abstract class AbstractTransformingDecodingInterceptor
        implements Interceptor {

    protected abstract InputStream transformInputStream(InputStream inputStream)
            throws IOException;

    @Override
    @SuppressWarnings("resource")
    public final Response intercept(final Chain chain)
            throws IOException {
        final Request request = chain.request();
        final Response response = chain.proceed(request);
        final ResponseBody body = response.body();
        return response.newBuilder()
                .body(ResponseBody.create(
                        body.contentType(),
                        body.contentLength(),
                        Okio.buffer(Okio.source(transformInputStream(body.byteStream())))
                ))
                .build();
    }

}

此实现还应该检测内容MIME类型,以免进行错误的转换,但是您可以自己轻松实现它.因此,这也是Base64和GZip的两个转换拦截器:

This implementation should also detect content MIME types in order not to do wrong transformations, but you can implement it yourself easily. So here are also two transforming interceptors for both Base64 and GZip:

final class Base64DecodingInterceptor
        extends AbstractTransformingDecodingInterceptor {

    private static final Interceptor base64DecodingInterceptor = new Base64DecodingInterceptor();

    private Base64DecodingInterceptor() {
    }

    static Interceptor getBase64DecodingInterceptor() {
        return base64DecodingInterceptor;
    }

    @Override
    protected InputStream transformInputStream(final InputStream inputStream) {
        return BaseEncoding.base64().decodingStream(new InputStreamReader(inputStream));
    }

}

final class GzipDecodingInterceptor
        extends AbstractTransformingDecodingInterceptor {

    private static final Interceptor gzipDecodingInterceptor = new GzipDecodingInterceptor();

    private GzipDecodingInterceptor() {
    }

    static Interceptor getGzipDecodingInterceptor() {
        return gzipDecodingInterceptor;
    }

    @Override
    protected InputStream transformInputStream(final InputStream inputStream)
            throws IOException {
        return new GZIPInputStream(inputStream);
    }

}

并对其进行测试:

private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .addInterceptor(getGzipDecodingInterceptor())
        .addInterceptor(getBase64DecodingInterceptor())
        .addInterceptor(getFakeContentInterceptor())
        .build();

private static final Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://whatever")
        .client(okHttpClient)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

private static final IService service = retrofit.create(IService.class);

public static void main(final String... args)
        throws IOException {
    final String body = service.get().execute().body();
    System.out.println(body);
}

请注意,getFakeContentInterceptor返回的假拦截器始终返回H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA,因此baseUrl甚至没有真实的URL.输出:

Note that getFakeContentInterceptor returns a fake interceptor that always returns H4sIAAAAAAAEACspKk0FAI1M/P0EAAAA so that baseUrl does not even have a real URL. The output:

true

true

这篇关于修改响应体改造2.2拦截器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆