2013-08-28 4 views
62

Я использую OAuth, и я должен помещать токен OAuth в свой заголовок каждый раз, когда я делаю запрос. Я вижу аннотацию @Header, но есть ли способ сделать ее параметризованной, чтобы я мог пройти во время выполнения?Android Retrofit Parameterized @Headers

Вот концепция

@Header({Authorization:'OAuth {var}', api_version={var} })

Вы можете передать их в во время выполнения?

@GET("/users") 
void getUsers(
    @Header("Authorization") String auth, 
    @Header("X-Api-Version") String version, 
    Callback<User> callback 
) 
+0

Вы когда-нибудь это выясняли? Мне нужно передать токен в заголовке также – theSociableme

+0

Я также ищу решение этого, из документации это похоже на [@Headers()] (http://square.github.io/retrofit/javadoc/retrofit/ http/Header.html) аннотации метода _adds fields_ к заголовку один за другим, но поддерживает только литералы. И [@Header ("параметр") Строка строки] (http://square.github.io/retrofit/javadoc/retrofit/http/Header.html) аннотация _replaces_ заголовок с указанным значением. – nana

+1

То же самое здесь, не удалось выяснить, как обрабатывать сеансы при использовании модификации. – feresr

ответ

89

Помимо использования @Header параметра, я предпочел бы использовать RequestInterceptor обновить все ваш запрос без изменения интерфейса. Используя что-то вроде:

RestAdapter.Builder builder = new RestAdapter.Builder() 
    .setRequestInterceptor(new RequestInterceptor() { 
     @Override 
     public void intercept(RequestFacade request) { 
      request.addHeader("Accept", "application/json;versions=1"); 
      if (isUserLoggedIn()) { 
       request.addHeader("Authorization", getToken()); 
      }      
     } 
    }); 

р/с: Если вы используете Retrofit2, вы должны заметить Interceptor вместо RequestInterceptor

Поскольку RequestInterceptor не более доступны в Модернизированный 2.0

+3

Это не связано напрямую, но если вам нужно получить значения из объекта запроса, чтобы создать заголовок авторизации, вам необходимо расширить ApacheClient и выполнить дублирование объекта Request (List

headers = ...; Запрос запросаNew = новый запрос (request.getMethod(), request.getUrl(), заголовки, request.getBody()); request = requestNew). –

+1

Это трюк, который помешает закодированному, лучше использовать ответ @ nana –

+0

'RestAdapter' зависит от Retrofit1, в Retrofit2 это' Retrofit'. Я собираюсь использовать Retrofit2, поэтому нет проблем, если вы используете 'RequestInterceptor', как указано выше? –

45

Да, вы можете передать их во время выполнения. На самом деле, в значительной степени точно так же, как вы его напечатали. Это будет в вашем классе интерфейса API, названный сказать SecretApiInterface.java

public interface SecretApiInterface { 

    @GET("/secret_things") 
    SecretThing.List getSecretThings(@Header("Authorization") String token) 

} 

Затем вы передаете параметры на этот интерфейс из вашего запроса, что-то вдоль этих линий: (этот файл будет, например SecretThingRequest. Java)

public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{ 

    private String token; 

    public SecretThingRequest(String token) { 
     super(SecretThing.List.class, SecretApiInterface.class); 
     this.token = token; 
    } 

    @Override 
    public SecretThing.List loadDataFromNetwork() { 
     SecretApiInterface service = getService(); 
     return service.getSecretThings(Somehow.Magically.getToken()); 
    } 
} 

где Somehow.Magically.getToken() является вызов метода, который возвращает маркер, это до вас, где и как вы определяете его.

Вы можете, конечно, иметь несколько аннотаций @Header("Blah") String blah в реализации интерфейса, как в вашем случае!

Я нашел его в заблуждение тоже the documentation ясно говорит, что заменяет заголовок, но НЕ!
Он фактически добавлен как с @Headers("hardcoded_string_of_liited_use") аннотацию

Надежда это помогает;)

+0

Я нашел в документах, что он не заменяет существующий заголовок: «Обратите внимание, что заголовки не перезаписывают друг друга». Проверьте http://square.github.io/retrofit/ и «Header Manipulation» – zatziky

+0

Это хорошая новость, возможно, это были исправления! – nana

27

Принятый ответ на более старая версия Retrofit. Для будущих зрителей способ сделать это с Retrofit 2,0 используют пользовательский OkHttp клиент:

OkHttpClient httpClient = new OkHttpClient.Builder() 
    .addInterceptor(new Interceptor() { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Builder ongoing = chain.request().newBuilder(); 
     ongoing.addHeader("Accept", "application/json;versions=1"); 
     if (isUserLoggedIn()) { 
     ongoing.addHeader("Authorization", getToken()); 
     } 
     return chain.proceed(ongoing.build()); 
    } 
    }) 
    .build(); 

Retrofit retrofit = new Retrofit.Builder() 
    // ... extra config 
    .client(httpClient) 
    .build(); 

Надеется, что это поможет кому-то. :)

+3

В обычном использовании с dagger2, retrofit2 будет singleton, поэтому httpclient не будет создан каждый раз. в этом случае isUserLoggedIn() не имеет смысла, я прав? Единственное решение, которое я могу видеть в настоящее время, - это принудительное повторное инициализацию retrofit2 при изменении статуса входа пользователя, чтобы соответствующий заголовок был добавлен или удален из запроса .. или есть какое-то очевидное решение, которое я не вижу в настоящее время? Спасибо. – bajicdusko

+0

@bajicdusko это моя точно такая же связь. Вы нашли решение? Кажется настолько расточительным и странным, что предыдущая версия была более эффективной. – deed02392

+0

@ deed02392 Вы можете установить составной «перехватчик», на который вы можете установить или перезагрузить перехватчик на более позднем этапе. Тем не менее, я бы сказал, что переоснащение как одноэлемент может стать признаком ранней оптимизации. На создание нового модифицированного экземпляра нет накладных расходов: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Retrofit.java – pablisco