Android Retrofit 매개 변수화 된 @Headers


85

OAuth를 사용하고 있으며 요청할 때마다 헤더에 OAuth 토큰을 넣어야합니다. 내가 볼 @Header주석을,하지만 난 실행시에 전달할 수 있도록이 파라미터 만들 수있는 방법은 무엇입니까?

여기에 개념이 있습니다

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

런타임에 전달할 수 있습니까?

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

당신은 이것을 알아 낸 적이 있습니까? 헤더에도 토큰을 전달해야합니다
theSociableme

나는 또한 이것에 대한 해결책을 찾고 있는데, 문서 에서 메서드의 @Headers () 주석이 필드 를 하나씩 헤더에 추가 하는 것처럼 들리지만 리터럴 만 지원합니다. 그리고 @Header ( "parameter") 문자열 문자열 매개 변수 주석은 헤더를 제공된 값으로 대체 합니다.
나나

2
여기에서도 마찬가지로 개조를 사용할 때 세션을 처리하는 방법을 찾을 수 없습니다.
FRR 2014 년

우리는 모든 항목을 통과 할 필요가 없었고 개조 자체가 모든 것을 처리했습니다. StackOverflow에서 내 대답 링크 를 확인하십시오 .
Subin Babu

답변:


98

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

p / s : Retrofit2를 사용 Interceptor하는 경우 대신 사용해야 합니다.RequestInterceptor

RequestInterceptorRetrofit 2.0에서 더 이상 사용할 수 없기 때문에


3
이것은 직접적인 관련이 없지만 Authorization 헤더를 생성하기 위해 요청 객체에서 값을 가져와야하는 경우 ApacheClient를 확장하고 Request 객체를 복제해야합니다 (List <Header> headers = ... ; 요청 requestNew = new Request (request.getMethod (), request.getUrl (), 헤더, request.getBody ()); request = requestNew).

1
즉 놨가 최대 코딩하는 트릭, 나나의 대답 @보다 효율적으로 사용할 수있어
이반 Fazaniuk

1
RestAdapterRetrofit1에 따라 다르지만 Retrofit2에서는 Retrofit. Retrofit2를 사용할 것이므로 RequestInterceptor위 코드와 같이 사용하면 문제가 없습니까?
Huy Tower

55

예, 런타임에 전달할 수 있습니다. 사실 입력 한 것과 거의 동일합니다. 이것은 SecretApiInterface.java 라는 이름의 API 인터페이스 클래스에 있습니다.

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귀하의 경우와 같이 인터페이스 구현에 하나 이상의 주석을 가질 수 있습니다 !

나는 그것도 혼란스럽고 문서 는 그것이 헤더를 대체 한다고 분명히 말하고 있지만 그렇지 않습니다 !
실제로 @Headers("hardcoded_string_of_liited_use")주석 과 같이 추가됩니다.

도움이 되었기를 바랍니다 ;)


1
문서에서 기존 헤더를 대체하지 않는다는 것을 발견했습니다. "헤더는 서로 덮어 쓰지 않습니다." 확인 square.github.io/retrofit 와 "헤더 조작"
Amio.io

37

허용되는 대답은 이전 버전의 Retrofit입니다. 미래의 시청자를 위해 Retrofit2.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();

누군가에게 도움이되기를 바랍니다. :)


5
dagger2와 함께 일반적으로 사용되는 경우 retrofit2는 싱글 톤이므로 매번 httpclient가 생성되지 않습니다. 이 경우 isUserLoggedIn ()이 의미가 없습니다. 맞습니까? 현재 내가 볼 수있는 유일한 해결책은 사용자 로그인 상태가 변경 될 때 retrofit2를 다시 초기화하여 적절한 헤더가 요청에서 추가되거나 제거되도록하는 것입니다. 또는 현재 볼 수없는 명백한 해결책이 있습니까? 감사.
bajicdusko

2
@bajicdusko 이것은 내 똑같은 수수께끼입니다. 해결책을 찾았습니까? 너무 낭비적이고 이상해서 이전 버전이 더 효율적이었습니다.
deed02392

@ deed02392 Interceptor나중에 인터셉터를 설정하거나 재설정 할 수 있는 컴포지트 를 설정할 수 있습니다 . 그러나 단일 항목으로 개조하는 것은 초기 최적화의 신호일 수 있다고 주장합니다. 새로운 개조 인스턴스를 만드는 방법에 대한 오버 헤드가 없습니다 : github.com/square/retrofit/blob/master/retrofit/src/main/java/...
pablisco

나는 그것에 대해 깊이 생각하지 않았습니다. dagger2로 초기화되는 일부 ApiFactory 클래스가 있으며 개조 초기화를 담당합니다. ApiFactory에서 필요할 때 개조 인스턴스를 강제로 다시 초기화하는 하나의 공용 메서드를 노출 했으므로 매우 간단합니다. 내가 잘못했을 수도 있지만 작업을 수행했으며 Authorization 헤더에만 사용하므로 사용자 로그인 또는 로그 아웃시 사용됩니다. 또 다른 옵션은 엔드 포인트 정의 내에서 @Header 어노테이션을 사용하는 것입니다. 실용적이지 않은 각 끝점에 설정해야합니다.
bajicdusko

@pablisco Ah 내 이해 Interceptor에서 Retrofit2 인스턴스를 만든 후에는 s를 추가하거나 제거 할 수 없습니다 .
deed02392

7

개조 2.3.0

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
    okHttpClientBuilder
            .addInterceptor(new Interceptor() {
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
                    return chain.proceed(newRequest.build());
                }
            });

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(GithubService.BASE_URL)
            .client(okHttpClientBuilder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

나는 이것을 GitHub에 연결하는 데 사용하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.