2015-06-11 17 views
22

Sto usando Retrofit con OkHttp Client e Jackson per Serializzazione Json e voglio ottenere l'intestazione della risposta.Ottenere intestazione dalla risposta (Retrofit/OkHttp Client)

So che posso estendere l'OkClient e intercettarlo. Ma questo viene prima che inizi il processo di deserializzazione.

Ciò di cui ho fondamentalmente bisogno è quello di ottenere l'intestazione insieme all'oggetto JSON deserializzato.

risposta

23

Con Retrofit 1.9.0, se si utilizza la versione asincrona richiamata dell'interfaccia,

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

Poi il callback riceveranno un Response oggetto

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

     } 

     @Override 
     public void failure(RetrofitError error) { 

     } 
    } 

che ha un metodo chiamato 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()); 
      } 
     } 

Per l'ingresso di Retrofit 2.0 rfaccia, puoi farlo con Call<T>.

Per il supporto Rx Retrofit 2.0, è possibile farlo con Observable<Result<T>>

+0

C'è un modo per ottenerlo in modo sincrono? – Sakiboy

+1

In Retrofit 1.9.0 no, in Retrofit 2.0+ si (usando 'Chiama .execute()') – EpicPandaForce

+0

Come posso farlo con osservabili? – Lester

20

In Retrofit 2.0.0, è possibile ottenere un colpo di testa in questo modo:

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 
    } 
}); 
+0

come faccio a scorrere tra tutte le intestazioni? Ho 4-5 intestazioni con "set-cookie" come chiave. – Prabs

+1

'Elenco cookieList = headers.toMultimap(). Get (" set-cookie ");' utilizza 'foreach' iterate attraverso l'elenco – Prabs

+0

In questo modo: headers.values ​​(" Set-Cookie "). – Edi

1

Proprio come te volevo le intestazioni lungo lato del carico utile. Avevo bisogno di accedere a Etag. Ci vuole un po 'di retrò-foo, ma puoi farlo. ecco cosa ho fatto. È un campione sporco, quindi non prendere questo esempio di best practice.

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); 
Problemi correlati