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