2015-06-11 14 views
22

Używam Retrofit z klientem OkHttp i Jacksona dla Json Serialization i chcę uzyskać nagłówek odpowiedzi.Uzyskiwanie nagłówka z odpowiedzią (Retrofit/OkHttp Client)

Wiem, że mogę przedłużyć OkClient i przechwycić go. Ale dzieje się to przed rozpoczęciem procesu deserializacji.

To, czego potrzebuję, to pobranie nagłówka wraz z deserializowanym obiektem Json.

Odpowiedz

23

z modernizacją 1.9.0, jeśli używasz oddzwan asynchroniczną wersję interfejsu,

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

Wtedy twój zwrotna otrzyma Response obiekt

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

     } 

     @Override 
     public void failure(RetrofitError error) { 

     } 
    } 

który ma metodę zwaną 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()); 
      } 
     } 

Dla wersji inte 2.0 rface, możesz to zrobić z Call<T>.

Na wsparcie modernizowanych 2,0 za Rx, można to zrobić z Observable<Result<T>>

+0

Czy istnieje sposób na synchronizację? – Sakiboy

+1

W Retroficie 1.9.0 nie, w Retroficie 2.0+ tak (używając 'Zadzwoń pod numer .execute()') – EpicPandaForce

+0

Jak mogę to zrobić z obserwowalnymi? – Lester

20

W Retrofit 2.0.0, można uzyskać nagłówek tak:

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

jak przechodzić przez wszystkie nagłówki? Mam 4-5 nagłówków z "set-cookie" jako klucz. – Prabs

+1

'List cookieList = headers.toMultimap(). Get (" set-cookie ");' przy użyciu 'foreach' iteracji poprzez listę – Prabs

+0

Lub jak to: headers.values ​​(" Set-Cookie "). – Edi

1

podobnie jak ciebie chciałem nagłówki wzdłuż strona ładunku. Potrzebowałem dostępu do Etag. Potrzeba trochę retro-foo, ale możesz to zrobić. Oto co zrobiłem. To brudna próbka, więc nie bierz tego jako przykład najlepszej praktyki.

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); 
Powiązane problemy