인터셉터를 사용하여 Retrofit 2.0에서 헤더를 추가하는 방법은 무엇입니까?


96

우리 팀은 Retrofit 2.0 을 채택하기로 결정했습니다. 대한 초기 연구를 진행 중입니다. 저는이 도서관의 초보자입니다.

Android 앱에서 Retrofits 2.0interceptor통해 사용자 지정 헤더를 추가 하는 방법을 궁금합니다 . Retrofit 1.X에서 헤더를 추가 하는 데 사용 하는 방법에 대한 많은 자습서 가 있지만 API가 최신 버전에서 많이 변경 되었기 때문에 새 버전에서 이러한 메서드를 적용하는 방법을 잘 모르겠습니다. 또한 Retrofit은 아직 새 문서를 업데이트하지 않았습니다.interceptor

예를 들어, 다음 코드에서 Interceptor추가 헤더를 추가 하려면 클래스를 어떻게 구현해야 합니까? 게다가, 문서화되지 않은 Chain개체 는 정확히 무엇 입니까? 은 언제 intercept()호출됩니까?

    OkHttpClient client = new OkHttpClient();
    client.interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());

            // How to add extra headers?

            return response;
        }
    });

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_API_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

1
로 확인하십시오 BASE_API_URL의 끝을 확인 /하고 당신의 API의 URL을하지 (할 stuff/post/whatever)
EpicPandaForce

답변:


120

이것 좀 봐.

public class HeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
                .newBuilder()
                .addHeader("appid", "hello")
                .addHeader("deviceplatform", "android")
                .removeHeader("User-Agent")
                .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0")
                .build();
        Response response = chain.proceed(request);
        return response;
    }
}

Kotlin

class HeaderInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response = chain.run {
        proceed(
            request()
                .newBuilder()
                .addHeader("appid", "hello")
                .addHeader("deviceplatform", "android")
                .removeHeader("User-Agent")
                .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0")
                .build()
        )        
    }
}

감사!! 그렇다면 이것은 intercept()응용 프로그램에서 요청이 전송 될 때마다 트리거됩니까? 리디렉션에 대한 중간 응답을 잡을 수 있습니까? 아니면 최종 응답을받을 수 있습니까?
hackjutsu

이것은 모든 요청에 ​​대해 호출되며 내가 옳다는 것을 알고 있다면 네트워크 인터셉터가 아닌 인터셉터로 추가하기 때문입니다. 여기서는 최종 응답 만받을 수 있다고 생각하지만 리디렉션을 내 머리 위에서 알지 못하는 리디렉션으로 볼 수있는 구성이있을 수 있습니다 (http URL 연결
용도

1
이 링크를 참조하십시오 : github.com/square/okhttp/wiki/Interceptors , 필요한 정보를 얻으십시오 :) 감사합니다 ~
hackjutsu

5
참고로 .NET 대신 빌더를 사용해야합니다 client.interceptors(). 이 모습은 좋아new OkHttpClient.Builder().addInterceptor(<Your Interceptor>).build()
글리

22

받아 들여진 답변의 또 다른 대안

public class HeaderInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        request = request.newBuilder()
                .addHeader("headerKey0", "HeaderVal0")
                .addHeader("headerKey0", "HeaderVal0--NotReplaced/NorUpdated") //new header added
                .build();

        //alternative
        Headers moreHeaders = request.headers().newBuilder()
                .add("headerKey1", "HeaderVal1")
                .add("headerKey2", "HeaderVal2")
                .set("headerKey2", "HeaderVal2--UpdatedHere") // existing header UPDATED if available, else added.
                .add("headerKey3", "HeaderKey3")
                .add("headerLine4 : headerLine4Val") //line with `:`, spaces doesn't matter.
                .removeAll("headerKey3") //Oops, remove this.
                .build();

        request = request.newBuilder().headers(moreHeaders).build();

        /* ##### List of headers ##### */
        // headerKey0: HeaderVal0
        // headerKey0: HeaderVal0--NotReplaced/NorUpdated
        // headerKey1: HeaderVal1
        // headerKey2: HeaderVal2--UpdatedHere
        // headerLine4: headerLine4Val

        Response response = chain.proceed(request);
        return response;
    }
}

좋은! 그래서 request.newBuilder().headers(moreHeaders).build()원래 헤더를 유지할까요?
hackjutsu

1
예. removeAll (String name) 이 호출 되지 않으면 요청에서 헤더가 제거되지 않습니다 .
VenomVendor

@VenomVendor 비슷한 질문 여기에 도움을 나를 기쁘게 stackoverflow.com/questions/45078720/... 감사
user606669

계속해서 새로운 개체가 생성되지 않습니까?
TheRealChx101

3
   public class ServiceFactory {  
    public static ApiClient createService(String authToken, String userName, String password) {
            OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(
                            chain -> {
                                Request request = chain.request().newBuilder()
                                        .headers(getJsonHeader(authToken))
                                        .build();
                                return chain.proceed(request);
                            })
                    .authenticator(getBasicAuthenticator(userName, password))
                    .build();
            return getService(defaultHttpClient);
        }
        private static Headers getJsonHeader(String authToken) {
            Headers.Builder builder = new Headers.Builder();
            builder.add("Content-Type", "application/json");
            builder.add("Accept", "application/json");
            if (authToken != null && !authToken.isEmpty()) {
                builder.add("X-MY-Auth", authToken);
            }
            return builder.build();
        }
        private static Authenticator getBasicAuthenticator(final String userName, final String password) {
            return (route, response) -> {
                String credential = Credentials.basic(userName, password);
                return response.request().newBuilder().header("Authorization", credential).build();
            };
        }
          private static ApiClient getService(OkHttpClient defaultHttpClient) {
            return new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(defaultHttpClient)
                    .build()
                    .create(ApiClient.class);
        }
}

2

다음과 같은 내장 메서드와 함께 인터셉터를 사용하여 헤더를 사용할 수 있습니다.

   interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            Request.Builder builder = original.newBuilder();

            builder.header("Authorization","Bearer "+ LeafPreference.getInstance(context).getString(LeafPreference.TOKEN));

            Request request = builder.method(original.method(), original.body())
                    .build();
            Log.e("request",request.urlString());
            Log.e("header",request.header("Authorization"));
            return chain.proceed(request);
        }
    });
}

이 장소에서 어떻게 상황 을 파악하고 있는지 알고 싶습니다 .
rupinderjeet

@rupinderjeet 아마도 final Context context매개 변수 목록에 있을 것 입니다.
TheRealChx101 jul.

@ TheRealChx101 context이것은 비즈니스 로직이기 때문에 여기에 있으면 안된다는 것을 지적하고 싶었습니다 .
rupinderjeet
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.