2013-08-28 13 views
62

Używam OAuth i muszę umieścić token OAuth w moim nagłówku za każdym razem, gdy zgłoszę żądanie. Widzę adnotację @Header, ale czy istnieje sposób jej sparametryzowania, aby można było ją przekazać w czasie wykonywania?Aktualizacja Androida Parametryzacja @Headers

Oto koncepcja

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

można przekazać je w czasie wykonywania?

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

Czy zdajesz sobie z tego sprawę? Muszę przekazać token w nagłówku również – theSociableme

+0

Szukam również rozwiązania tego problemu, z dokumentacji, która brzmi jak [@Headers()] (http://square.github.io/retrofit/javadoc/retrofit/ http/Header.html) adnotacja na temat metody _adds fields_ do nagłówka jeden po drugim, ale obsługuje tylko literały. I [@Header ("parametr") Ciąg znaków] (http://square.github.io/retrofit/javadoc/retrofit/http/Header.html) Adnotacja parametrów _replaces_ nagłówka z podaną wartością. – nana

+1

To samo dotyczy, nie można dowiedzieć się, jak obsługiwać sesje podczas korzystania z modernizacji. – feresr

Odpowiedz

89

Poza tym przy użyciu @Header parametr, wolałbym użyć RequestInterceptor zaktualizować wszystkie żądania bez zmiany interfejsu. Korzystanie coś takiego:

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()); 
      }      
     } 
    }); 

p/s: Jeśli używasz Retrofit2, należy zauważyć Interceptor zamiast RequestInterceptor

Od RequestInterceptor nie jest już dostępna w Retrofit 2,0

+3

To nie jest bezpośrednio powiązane, ale jeśli potrzebujesz wygenerować wartości z obiektu żądania w celu wygenerowania nagłówka Authorization, musisz rozszerzyć ApacheClient i wykonać kopię obiektu Request (lista

headers = ...; Żądanie requestNew = new Request (request.getMethod(), request.getUrl(), nagłówki, request.getBody()); request = requestNew). –

+1

To jest sztuczka polegająca na zakodowaniu, lepszym wykorzystaniu odpowiedzi @ nana –

+0

"RestAdapter" zależy od Retrofit1, w Retrofit2 to "Retrofit". Zamierzam użyć Retrofit2, więc nie ma problemów, jeśli użyjesz 'RequestInterceptor' jak powyższy kod? –

45

Tak, można przekazać je w czasie wykonywania. W rzeczywistości, dokładnie tak, jak to napisałeś. Byłoby to w swojej klasie interfejsu API o nazwie powiedzieć SecretApiInterface.java

public interface SecretApiInterface { 

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

} 

Następnie przekazać parametry do tego interfejsu od Państwa potrzeb, coś wzdłuż tych linii: (plik ten byłby na przykład 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()); 
    } 
} 

gdzie Somehow.Magically.getToken() jest wywołanie metody, która zwraca token, to do ciebie, gdzie i jak go zdefiniować.

Możesz oczywiście mieć więcej niż jedną adnotację @Header("Blah") String blah w implementacji interfejsu, tak jak w twoim przypadku!

znalazłem to zbyt niejasna, the documentation wyraźnie mówi, że zastępuje nagłówek, ale nie!
To jest w rzeczywistości dodał jak z @Headers("hardcoded_string_of_liited_use") adnotacji

nadzieję, że to pomaga;)

+0

Znalazłem w dokumentach, że nie zastępuje istniejącego nagłówka: "Zwróć uwagę, że nagłówki nie zastępują się nawzajem." Sprawdź http://square.github.io/retrofit/ i "Header Manipulation" – zatziky

+0

To dobra wiadomość, to musiały być poprawki! – nana

27

Zaakceptowanych odpowiedź jest dla starsza wersja Retrofit. Dla przyszłych widzów sposób to zrobić z Retrofit 2.0 używa niestandardowego klienta 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(); 

Mam nadzieję, że ktoś pomoże. :)

+3

W powszechnym użyciu z sztyletem 2, retrofit2 będzie singleton, dlatego też httpclient nie będzie tworzony za każdym razem. w takim przypadku isUserLoggedIn() nie ma sensu, mam rację? Jedyne rozwiązanie, które widzę obecnie, to wymuszenie reinicjalizacji retrofit2 po zmianie loginu użytkownika, tak aby odpowiedni nagłówek został dodany lub usunięty z żądania. Czy istnieje jakieś oczywiste rozwiązanie, którego nie widzę obecnie? Dzięki. – bajicdusko

+0

@bajicdusko to jest dokładnie to samo zagadnienie. Znalazłeś rozwiązanie? Wydaje się to tak marnotrawne i dziwne, że poprzednia wersja była bardziej wydajna. – deed02392

+0

@ deed02392 Możesz ustawić złożony "Interceptor", na którym można ustawić lub zresetować przechwytywacz na późniejszym etapie. Twierdzę jednak, że modernizacja jako singleton może być oznaką wczesnej optymalizacji. Nie ma żadnych kosztów związanych z tworzeniem nowej instancji modernizacji: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Retrofit.java – pablisco

Powiązane problemy