2016-05-19 12 views
5

Ich versuche, eine Serverantwort zu verarbeiten, die GZIP ist. Die Antwort kommt mit einem KopfRetrofit: wie GZIP Antwort ohne Content-Encoding zu analysieren: Gzip-Header

Content-Type: application/x-gzip 

hat aber keine Header

Content-Encoding: gzip 

Wenn ich diesen Header mit einem Proxy hinzufügen, wird die Antwort einfach gut analysiert. Ich habe keine Kontrolle über den Server, daher kann ich die Kopfzeile nicht hinzufügen.

Kann ich Retrofit zwingen, es als GZIP-Inhalt zu behandeln? Gibt es einen besseren Weg? Die URL für den Server lautet: http://crowdtorch.cms.s3.amazonaws.com/4474/Updates/update-1.xml

Antwort

1

es eine Möglichkeit, besser ist als das Rad neu erfinden. Fügen Sie einfach die Kopfzeile hinzu.

.addNetworkInterceptor((Interceptor.Chain chain) -> { 
    Request req = chain.request(); 
    Headers.Builder headersBuilder = req.headers().newBuilder(); 

    String credential = Credentials.basic(...); 
    headersBuilder.set("Authorization", credential); 

    Response res = chain.proceed(req.newBuilder().headers(headersBuilder.build()).build()); 

    return res.newBuilder() 
     .header("Content-Encoding", "gzip") 
     .header("Content-Type", ""application/json") 
     .build(); 
}) 

In der Tat ist der Code ein klassisches Beispiel für die Übel der internen Code (wie com.sun Pakete aus dem JDK). RealResponseBody hat diesen Konstruktor nicht mehr.

+0

Interessant. Benutze einen Abfangjäger. Gute Idee. Klingt so, als müsste es funktionieren. – itsymbal

+0

@itsymbal es tut, ich benutze es –

6

Ich fand es heraus. Die Idee besteht darin, einen benutzerdefinierten Interceptor hinzuzufügen, der die noch nicht entpackte Antwort übernimmt und sie manuell entzippt. Tun Sie das gleiche, was OkHttp automatisch basierend auf dem Content-Encoding-Header tun würde, ohne jedoch diesen Header zu benötigen.

ist wie dis:

OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() 
      .addInterceptor(new UnzippingInterceptor()); 
    OkHttpClient client = clientBuilder.build(); 

Und der Interceptor ist wie dis:

private class UnzippingInterceptor implements Interceptor { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Response response = chain.proceed(chain.request()); 
     return unzip(response); 
    } 
} 

Und die unzip Funktion ist wie dis:

// copied from okhttp3.internal.http.HttpEngine (because is private) 
private Response unzip(final Response response) throws IOException { 

    if (response.body() == null) { 
     return response; 
    } 

    GzipSource responseBody = new GzipSource(response.body().source()); 
    Headers strippedHeaders = response.headers().newBuilder() 
      .removeAll("Content-Encoding") 
      .removeAll("Content-Length") 
      .build(); 
    return response.newBuilder() 
      .headers(strippedHeaders) 
      .body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody))) 
      .build(); 
}