webentwicklung-frage-antwort-db.com.de

Header aus Antwort abrufen (Retrofit / OkHttp Client)

Ich verwende Retrofit mit dem OkHttp-Client und Jackson für die Json-Serialisierung und möchte den Header der Antwort abrufen.

Ich weiß, dass ich den OkClient erweitern und abfangen kann. Dies geschieht jedoch, bevor der Deserialisierungsprozess beginnt.

Was ich grundsätzlich brauche, ist, den Header zusammen mit dem deserialisierten Json-Objekt abzurufen.

38
dknaack

Wenn Sie mit Retrofit 1.9.0 die asynchrone Callback-Version der Schnittstelle verwenden,

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

Dann erhält Ihr Rückruf ein Response Objekt

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

        }

        @Override
        public void failure(RetrofitError error) {

        }
    }

Welches hat eine Methode namens 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());
            }
        }

Für die Oberfläche von Retrofit 2.0 können Sie dies mit Call<T> Tun.

Für die Rx-Unterstützung von Retrofit 2.0 können Sie dies mit Observable<Result<T>> tun

41
EpicPandaForce

In Retrofit 2.0.0 können Sie Header wie folgt erhalten:

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

Ähnlich wie Sie wollte ich die Header neben der Nutzlast haben. Ich brauchte Zugang zum Etag. Es braucht ein bisschen Retro-Foo, aber du kannst es schaffen. hier ist was ich getan habe. Es ist eine schmutzige Probe, nehmen Sie sie also nicht als Best-Practice-Probe.

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