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.
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
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
}
});
Ä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);