web-dev-qa-db-fra.com

Obtenir l'en-tête de la réponse (client Retrofit / OkHttp)

J'utilise Retrofit avec le client OkHttp et Jackson pour la sérialisation Json et je souhaite obtenir l'en-tête de la réponse.

Je sais que je peux étendre l'OkClient et l'intercepter. Mais ceci intervient avant le début du processus de désérialisation.

Ce dont j'ai essentiellement besoin, c’est d’obtenir l’en-tête à côté de l’objet Json désérialisé.

38
dknaack

Avec Retrofit 1.9.0, si vous utilisez la version asynchrone de rappel,

@GET("/user")
void getUser(Callback<User> callback)

Ensuite, votre callback recevra un objet Response

    Callback<User> user = new Callback<User>() {
        @Override
        public void success(User user, Response response) {

        }

        @Override
        public void failure(RetrofitError error) {

        }
    }

Qui a une méthode appelée getHeaders()

    Callback<User> user = new Callback<User>() {
        @Override
        public void success(User user, Response response) {
            List<Header> headerList = response.getHeaders();
            for(Header header : headerList) {
                Log.d(TAG, header.getName() + " " + header.getValue());
            }
        }

Pour l'interface de Retrofit 2.0, vous pouvez le faire avec Call<T>.

Pour le support Rx de Retrofit 2.0, vous pouvez le faire avec Observable<Result<T>>

41
EpicPandaForce

Dans Retrofit 2.0.0, vous pouvez obtenir un en-tête comme ceci:

public interface Api {
    @GET("user")
    Call<User> getUser();
}

Call<User> call = api.getUser();
call.enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        // get headers
        Headers headers = response.headers();
        // get header value
        String cookie = response.headers().get("Set-Cookie");
        // TODO
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {
        // TODO
    }
});
35
Spark.Bao

Tout comme vous, je voulais les en-têtes à côté de la charge utile. J'avais besoin d'accéder à l'Etag. Il faut du rétro-foo, mais vous pouvez le faire. voici ce que j'ai fait. C'est un échantillon sale, alors ne prenez pas cela comme un exemple de bonnes pratiques.

public static RestAdapter.Builder getRestBuilder(Context context) {
    GsonBuilder gsonBuilder = GsonBuilderUtils.getBuilder();
    Gson gson = gsonBuilder.create();
    // **
    // 1. create our own custom deserializer here
    // **
    final MyGsonConverter gsonConverter = new MyGsonConverter(gson);
    OkHttpClient httpClient = MyPersonalOkHttpFactory.getInstance().getAuthHttpClient(context);
    httpClient.networkInterceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            Response response = chain.proceed(originalRequest);
            // **
            // 2. add the headers from the Interceptor to our deserializer instance
            // **
            gsonConverter.headers = response.headers();
            return response;
        }
    });
    RestAdapter.Builder builder = new RestAdapter.Builder()
            .setClient(new OkClient(httpClient))
            .setEndpoint(Common.getApiOriginUrl())
            .setConverter(gsonConverter);
    return builder;
}

private static class MyGsonConverter extends GsonConverter {

    private Headers headers;

    public MyGsonConverter(Gson gson) {
        super(gson);
    }

    @Override
    public Object fromBody(TypedInput body, Type type) throws ConversionException {
        Object obj =  super.fromBody(body, type);
        // **
        // 3. at this point, gson is called and you have access to headers
        // do whatever you want here. I just set it on the return object.
        // ** 
        if (obj instanceof HeadersArrayList) {
            ((HeadersArrayList)obj).setHeaders(headers);
        }
        return obj;
    }
}

public class HeadersArrayList<K> extends ArrayList<K>{

    private Headers headers;

    public Headers getHeaders() {
        return headers;
    }

    public void setHeaders(Headers headers) {
        this.headers = headers;
    }
}

// the retrofit api for reference
@GET("/api/of/my/backend/{stuff}")
HeadersArrayList<String> getSomething(@Path("stuff") String stuff);
2
whizzle