Làm thế nào để sử dụng bộ chặn để thêm Tiêu đề trong Retrofit 2.0?


95

Nhóm của chúng tôi quyết định áp dụng Retrofit 2.0 và tôi đang thực hiện một số nghiên cứu ban đầu về nó. Tôi là một người mới đến thư viện này.

Tôi đang tự hỏi làm thế nào để sử dụng interceptorđể thêm tiêu đề tùy chỉnh qua Retrofits 2.0 trong ứng dụng Android của chúng tôi. Có rất nhiều hướng dẫn về cách sử dụng interceptorđể thêm tiêu đề trong Retrofit 1.X, nhưng vì các API đã thay đổi rất nhiều trong phiên bản mới nhất, tôi không chắc làm thế nào để điều chỉnh các phương pháp đó trong phiên bản mới. Ngoài ra, Retrofit vẫn chưa cập nhật tài liệu mới của mình.

Ví dụ, trong các mã sau, tôi nên triển khai Interceptorlớp như thế nào để thêm các tiêu đề phụ? Ngoài ra, đối tượng không có giấy tờChain chính xác là gì? Khi nào sẽ intercept()được gọi?

    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
Đảm bảo rằng BASE_API_URL của bạn kết thúc bằng /và các url API của bạn không kết thúc bằng ( stuff/post/whatever)
EpicPandaForce

Câu trả lời:


119

Kiểm tra điều này.

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

Cảm ơn!! Vì vậy, điều này intercept()được kích hoạt mỗi khi một yêu cầu được gửi từ ứng dụng? Chúng ta có thể bắt được phản hồi trung gian để chuyển hướng hay chỉ nhận được phản hồi cuối cùng?
hackjutsu

Điều này được gọi cho mọi yêu cầu, và nếu tôi biết là đúng, đó là vì bạn thêm nó như một bộ đánh chặn, chứ không phải như một bộ đánh chặn mạng. Tôi nghĩ rằng bạn chỉ có thể nhận được phản hồi cuối cùng ở đây, nhưng có thể có một cấu hình để cho phép xem chuyển hướng là chuyển hướng mà tôi không biết (cũng có một cấu hình cho kết nối URL http.)
EpicPandaForce

1
Chỉ cần tham khảo liên kết này: github.com/square/okhttp/wiki/Interceptors , và nhận được thông tin mà tôi cần :) Cảm ơn bạn ~
hackjutsu

5
Fyi, bạn cần sử dụng một trình xây dựng thay vì client.interceptors(). Điều này trông giống nhưnew OkHttpClient.Builder().addInterceptor(<Your Interceptor>).build()
GLee

22

Một thay thế khác từ câu trả lời được chấp nhận

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

Đẹp! Vì vậy, request.newBuilder().headers(moreHeaders).build()sẽ giữ các tiêu đề ban đầu?
hackjutsu 13/10/15

1
Đúng. Không có tiêu đề nào bị xóa khỏi yêu cầu trừ khi removeAll (Tên chuỗi) được gọi.
VenomVendor

@VenomVendor lòng giúp đỡ tôi với một câu hỏi tương tự ở đây stackoverflow.com/questions/45078720/... nhờ
user606669

Điều này sẽ không tiếp tục tạo ra các đối tượng mới?
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

Bạn có thể tiêu đề bằng cách sử dụng Interceptors với các phương thức tích hợp của nó như thế này

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

Tôi muốn biết làm thế nào để bạn có được bối cảnh tại nơi này?
rupinderjeet

@rupinderjeet Có thể là một final Context contexttrong danh sách các tham số.
TheRealChx101

@ TheRealChx101 Chỉ muốn chỉ ra rằng chúng ta không nên có contextở đây vì đây là logic nghiệp vụ.
rupinderjeet,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.