使用 Retrofit 2 向所有请求添加 header

Adding header to all request with Retrofit 2

Retrofit 2's documentation 说:

Headers that need to be added to every request can be specified using an OkHttp interceptor.

使用以前的版本可以轻松完成,here's相关QA。

但是使用改造 2,我找不到类似 setRequestInterceptorsetInterceptor 的方法可以应用于 Retrofit.Builder object。

另外 OkHttp anymore. Retrofit's doc refers us to Interceptor 中似乎没有 RequestInterceptor ,我不太明白如何将其用于此目的。

我该怎么做?

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

httpClient.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request().newBuilder().addHeader("parameter", "value").build();
        return chain.proceed(request);
    }
});
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl(url).client(httpClient.build()).build();

最新改造版本在这里 -> 2.1.0.

lambda 版本:

  builder.addInterceptor(chain -> {
    Request request = chain.request().newBuilder().addHeader("key", "value").build();
    return chain.proceed(request);
  });

丑陋的长版:

  builder.addInterceptor(new Interceptor() {
    @Override public Response intercept(Chain chain) throws IOException {
      Request request = chain.request().newBuilder().addHeader("key", "value").build();
      return chain.proceed(request);
    }
  });

完整版:

class Factory {

public static APIService create(Context context) {

  OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
  builder.readTimeout(10, TimeUnit.SECONDS);
  builder.connectTimeout(5, TimeUnit.SECONDS);

  if (BuildConfig.DEBUG) {
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
    builder.addInterceptor(interceptor);
  }

  builder.addInterceptor(chain -> {
    Request request = chain.request().newBuilder().addHeader("key", "value").build();
    return chain.proceed(request);
  });

  builder.addInterceptor(new UnauthorisedInterceptor(context));
  OkHttpClient client = builder.build();

  Retrofit retrofit =
      new Retrofit.Builder().baseUrl(APIService.ENDPOINT).client(client).addConverterFactory(GsonConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();

  return retrofit.create(APIService.class);
  }
}

gradle文件(如果要使用,需要添加日志拦截器):

  //----- Retrofit
  compile 'com.squareup.retrofit2:retrofit:2.1.0'
  compile "com.squareup.retrofit2:converter-gson:2.1.0"
  compile "com.squareup.retrofit2:adapter-rxjava:2.1.0"
  compile 'com.squareup.okhttp3:logging-interceptor:3.4.0'

在我的例子中 addInterceptor() 无法将 HTTP headers 添加到我的请求中,我不得不使用 addNetworkInterceptor()。代码如下:

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addNetworkInterceptor(new AddHeaderInterceptor());

拦截器代码:

public class AddHeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {

        Request.Builder builder = chain.request().newBuilder();
        builder.addHeader("Authorization", "MyauthHeaderContent");

        return chain.proceed(builder.build());
    }
}

这个和 this gist

上的更多示例

为了记录您的请求和响应,您需要一个拦截器,并且为了设置 header 您需要一个拦截器,这是使用改造 2.1

同时添加两个拦截器的解决方案
 public OkHttpClient getHeader(final String authorizationValue ) {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient okClient = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .addNetworkInterceptor(
                        new Interceptor() {
                            @Override
                            public Response intercept(Interceptor.Chain chain) throws IOException {
                                Request request = null;
                                if (authorizationValue != null) {
                                    Log.d("--Authorization-- ", authorizationValue);

                                    Request original = chain.request();
                                    // Request customization: add request headers
                                    Request.Builder requestBuilder = original.newBuilder()
                                            .addHeader("Authorization", authorizationValue);

                                    request = requestBuilder.build();
                                }
                                return chain.proceed(request);
                            }
                        })
                .build();
        return okClient;

    }

现在在您的改造中 object 在客户端中添加此 header

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .client(getHeader(authorizationValue))
                .addConverterFactory(GsonConverterFactory.create())
                .build();

如果使用 addInterceptor 方法添加 HttpLoggingInterceptor,它将不会记录由晚于 HttpLoggingInterceptor 应用的其他拦截器添加的内容。

例如:如果你有两个拦截器 "HttpLoggingInterceptor" 和 "AuthInterceptor",并且 HttpLoggingInterceptor 首先应用,那么你 无法查看 AuthInterceptor 设置的 http-params 或 headers。

OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addNetworkInterceptor(logging)
.addInterceptor(new AuthInterceptor());

我通过使用 addNetworkInterceptor 方法解决了它。

为 Retrofit 1.9 和 2.0 尝试这种类型 header。对于 Json 内容类型。

@Headers({"Accept: application/json"})
@POST("user/classes")
Call<playlist> addToPlaylist(@Body PlaylistParm parm);

您可以添加更多 header,即

@Headers({
        "Accept: application/json",
        "User-Agent: Your-App-Name",
        "Cache-Control: max-age=640000"
    })

动态添加到 headers:

@POST("user/classes")
Call<ResponseModel> addToPlaylist(@Header("Content-Type") String content_type, @Body RequestModel req);

叫你方法即

mAPI.addToPlayList("application/json", playListParam);

想要每次都通过,然后使用 http 拦截器创建 HttpClient object:

OkHttpClient httpClient = new OkHttpClient();
        httpClient.networkInterceptors().add(new Interceptor() {
            @Override
            public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
                Request.Builder requestBuilder = chain.request().newBuilder();
                requestBuilder.header("Content-Type", "application/json");
                return chain.proceed(requestBuilder.build());
            }
        });

然后添加改造object

Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(httpClient).build();

更新 如果您使用的是 Kotlin,请删除 { } 否则它将不起作用

使用这个改造客户端

class RetrofitClient2(context: Context) : OkHttpClient() {

    private var mContext:Context = context
    private var retrofit: Retrofit? = null

    val client: Retrofit?
        get() {
            val logging = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)

            val client = OkHttpClient.Builder()
                    .connectTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
                    .readTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
                    .writeTimeout(Constants.TIME_OUT, TimeUnit.SECONDS)
            client.addInterceptor(logging)
            client.interceptors().add(AddCookiesInterceptor(mContext))

            val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create()
            if (retrofit == null) {

                retrofit = Retrofit.Builder()
                        .baseUrl(Constants.URL)
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        .client(client.build())
                        .build()
            }
            return retrofit
        }
}

我将 JWT 与每个请求一起传递。请不要介意变量名,这有点令人困惑。

class AddCookiesInterceptor(context: Context) : Interceptor {
    val mContext: Context = context
    @Throws(IOException::class)
    override fun intercept(chain: Interceptor.Chain): Response {
        val builder = chain.request().newBuilder()
        val preferences = CookieStore().getCookies(mContext)
        if (preferences != null) {
            for (cookie in preferences!!) {
                builder.addHeader("Authorization", cookie)
            }
        }
        return chain.proceed(builder.build())
    }
}

在 kotlin 中添加拦截器看起来是这样的:

.addInterceptor{ it.proceed(it.request().newBuilder().addHeader("Cache-Control", "no-store").build())}

RetrofitHelper 库用 kotlin 编写,可以让您使用几行代码进行 API 调用。

像这样在您的应用程序 class 中添加 headers:

class Application : Application() {

    override fun onCreate() {
    super.onCreate()

        retrofitClient = RetrofitClient.instance
                    //api url
                .setBaseUrl("https://reqres.in/")
                    //you can set multiple urls
        //                .setUrl("example","http://ngrok.io/api/")
                    //set timeouts
                .setConnectionTimeout(4)
                .setReadingTimeout(15)
                    //enable cache
                .enableCaching(this)
                    //add Headers
                .addHeader("Content-Type", "application/json")
                .addHeader("client", "android")
                .addHeader("language", Locale.getDefault().language)
                .addHeader("os", android.os.Build.VERSION.RELEASE)
            }

        companion object {
        lateinit var retrofitClient: RetrofitClient

        }
    }  

然后拨打电话:

retrofitClient.Get<GetResponseModel>()
            //set path
            .setPath("api/users/2")
            //set url params Key-Value or HashMap
            .setUrlParams("KEY","Value")
            // you can add header here
            .addHeaders("key","value")
            .setResponseHandler(GetResponseModel::class.java,
                object : ResponseHandler<GetResponseModel>() {
                    override fun onSuccess(response: Response<GetResponseModel>) {
                        super.onSuccess(response)
                        //handle response
                    }
                }).run(this)

有关详细信息,请参阅 documentation

Kotlin 版本为

fun getHeaderInterceptor():Interceptor{
    return object : Interceptor {
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            val request =
            chain.request().newBuilder()
                    .header(Headers.KEY_AUTHORIZATION, "Bearer.....")
                    .build()
            return chain.proceed(request)
        }
    }
}


private fun createOkHttpClient(): OkHttpClient {
    return OkHttpClient.Builder()
            .apply {
                if(BuildConfig.DEBUG){
                    this.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
                }
            }
            .addInterceptor(getHeaderInterceptor())
            .build()
}