2015-04-26 17 views
30

Sto utilizzando un'API che utilizza uno schema di autorizzazione che richiede un'intestazione speciale "X-Authorization" da impostare per autenticare la richiesta. Ad esempio, questa configurazione Retrofit funziona perfettamente per l'utente la cui autenticazione token è abc123:Come impostare dinamicamente intestazioni in Retrofit (Android)

@Headers("X-Authorization: abc123") 
@GET("/posts") 
Observable<List<Post>> get_posts(); 

I cache dei token X-autorizzazione dell'utente, in modo da avere accesso a questo, però, non posso farlo cadere in la dichiarazione @Headers.

@Headers("X-Authorization: " + token) 
@GET("/posts") 
Observable<List<Post>> get_posts(); 

ottengo un errore di compilazione qui: Error:(41, 34) error: element value must be a constant expression

Tutte le idee su come avrei potuto ottenere intorno a questo?

risposta

56

Dal Retrofit 2.0 si hanno due opzioni


1) Utilizzando OkHttp 2.2+ utilizzare Interceptor

A livello Http, hai più controllo sulla richiesta, in modo che si possa fare cose come l'applicazione intestazioni solo a una richiesta specifica inviata a un endpoint specifico e così via.

public class MyOkHttpInterceptor implements Interceptor { 

@Override 
public Response intercept(Chain chain) throws IOException { 
    Request originalRequest = chain.request(); 
    if (!"/posts".contains(originalRequest.url())) { 
     return chain.proceed(originalRequest); 
    } 

    String token = // get token logic 

    Request newRequest = originalRequest.newBuilder() 
     .header("X-Authorization", token) 
     .build(); 

    return chain.proceed(newRequest); 
} 

[...] 

OkHttpClient okHttpClient = new OkHttpClient(); 
okHttpClient.networkInterceptors().add(new MyOkHttpInterceptor()); 
OkClient okClient = new OkClient(okHttpClient); 
YourApi api = new RestAdapter.Builder() 
      .setEndpoint(url) 
      .setClient(okClient) 
      .build() 
      .create(YourApi.class); 

Edit: Aggiunta @JakeWarthon commento come un'altra opzione come è anche valido.

2) Immettere @Header su un parametro del metodo e passarlo come valore durante il richiamo.

Dal docs:

// Replaces the header with the the value of its target. 
@GET("/") 
void foo(@Header("Accept-Language") String lang, Callback<Response> cb); 

parametri intestazione può essere nullo che li omettere dalla richiesta. Passare una lista o un array darà come risultato un'intestazione per ogni oggetto non nullo.

Nota: le intestazioni non si sovrascrivono. Tutte le intestazioni con lo stesso nome saranno incluse nella richiesta.


EDIT: Questa opzione non dovrebbe essere considerato come retrofit 2. * cessato il supporto per intercettori.

3) l'utente retrofit RequestInterceptor

Dalla documentazione: Intercept ogni richiesta prima che venga eseguita al fine di aggiungere ulteriori dati.

Si potrebbe fare qualcosa di simile

public class MyRetrofitInterceptor implements RequestInterceptor { 

@Override 
public void intercept(RequestFacade req) { 
    String token = // get token logic 
    if (token != null) { 
     req.addHeader("X-Authorization", token); 
    } 
} 

[...] 

YourApi api = new RestAdapter.Builder() 
      .setEndpoint(url) 
      .setRequestInterceptor(new MyRetrofitInterceptor()) 
      .build() 
      .create(YourApi.class); 

Il "problema" di questo approccio è che l'intercettatore otterrà eseguito su tutti gli endpoint, come è impostato a livello di RestAdapter, e non per ogni endpoint.Inoltre, lo RequestFacade non espone molte informazioni sulla richiesta, quindi nessuna possibilità di aggiungere molta logica attorno ad essa.

+0

Risposta brillante. Grazie per questo. – johncorser

+0

Link nella prima opzione non trovata: '1) User retrofit RequestInterceptor' ... qualche correzione? – Bhuro

Problemi correlati