Retrofit 2.0 - 添加 header 不起作用

Retrofit 2.0 - Adding header does not work

我正在开发一个 Android 应用程序,我想在其中使用 Retrofit 调用一个 API。 API 需要 header 中的授权令牌,我也添加了相同的内容。

下面是代码片段

RetrofitClient.kt

object RetrofitClient {
    var apiInterface: APIInterface? = null
    val okHttpClient = OkHttpClient.Builder()
        .connectTimeout(300, TimeUnit.SECONDS)
        .writeTimeout(300, TimeUnit.SECONDS)
        .readTimeout(180, TimeUnit.SECONDS)

    @Synchronized
    fun getClient(context: Context): APIInterface {
        if (apiInterface == null) {
            if (SharedPreference.isAuthTokenExists(context))
                okHttpClient.addInterceptor(HeaderInterceptor(context))
            apiInterface =
                Retrofit.Builder()
                    .baseUrl(context.resources.getString(R.string.base_url))
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(okHttpClient.build())
                    .build().create<APIInterface>(APIInterface::class.java)
        }
        return apiInterface as APIInterface
    }

 }

HeaderInterceptor.kt

class HeaderInterceptor(private val context: Context) : Interceptor {
    private val HEADER_TOKEN = "token"
    override fun intercept(chain: Interceptor.Chain): Response = chain.run {
        proceed(
            request()
                .newBuilder()
                .addHeader(
                    HEADER_TOKEN, "Bearer " + SharedPreference.initialize(context).getString(
                        Extras.AUTH_TOKEN, ""
                    )
                ).build()

        )
    }
}

APIInterface.kt

interface APIInterface {

    @POST("dialtogo/otp/verification")
    fun submitOTP(@Body otpModel: OTPModel): Call<ResponseFormat.GenericResponse?>?

     }

OTPRepository.kt

class OTPRepository(private var ctx: Context) {

    fun submitOTP(otpModel: OTPModel) {
        val apiInterface: APIInterface = RetrofitClient.getClient(ctx)
        val call: Call<ResponseFormat.GenericResponse?>? = apiInterface
            .submitOTP(otpModel)
        call?.enqueue(object : Callback<ResponseFormat.GenericResponse?> {
            override fun onResponse(
                call: Call<ResponseFormat.GenericResponse?>?,
                response: Response<ResponseFormat.GenericResponse?>
            ) {
                if (response.isSuccessful)
                    (ctx as dial.to.go.utils.Response)
                        .onSuccessResponse(response.body() as ResponseFormat.GenericResponse)
                else
                    (ctx as dial.to.go.utils.Response)
                        .onErrorResponse(response.errorBody().toString())
            }

            override fun onFailure(call: Call<ResponseFormat.GenericResponse?>?, t: Throwable?) {
                (ctx as dial.to.go.utils.Response)
                    .onFailure(t?.message)
            }
        })
    }
}

我在响应中收到 400 错误请求

我在没有 header 的情况下调用的 API 调用中没有发现任何问题。我的意思是,如果 SharedPreference.isAuthTokenExists(context) returns 为假,它工作正常。而且,仅供参考,它在 POSTMAN.

中工作正常

请任何人帮助我找出解决方案。

我对 Kotlin 不太熟悉,但是您正在清除请求并且只发送 header。

HeaderInterceptor.kt 在 Java 中会是:

Request request = original.newBuilder()
                        .addHeader(HEADER_TOKEN, "Bearer " + SharedPreference.initialize(context).getString(Extras.AUTH_TOKEN, "")
                        .method(original.method(), original.body())
                        .build();
return chain.proceed(request);

尝试在 ApiInterface 的 fun submitOTP 中使用 @Header("Authorization") 并将令牌作为参数传递。

我想问题是第一次,因为令牌不存在,它会在没有 HeaderInterceptor 的情况下创建 apiInterface,然后因为它是 singleton,它将继续使用相同的客户端和不会再添加 header,更好的选择是尽管有令牌 exists/not 只需添加 HeaderInterceptor,因为它不会导致任何问题

@Synchronized
    fun getClient(context: Context): APIInterface {
        if (apiInterface == null) { 
            //removed the check for exists
            okHttpClient.addInterceptor(HeaderInterceptor(context))
            apiInterface =
                Retrofit.Builder()
                    .baseUrl(context.resources.getString(R.string.base_url))
                    .addConverterFactory(GsonConverterFactory.create())
                    .client(okHttpClient.build())
                    .build().create<APIInterface>(APIInterface::class.java)
        }
        return apiInterface as APIInterface
    }

将您的HeaderInterceptor更改为以下

class HeaderInterceptor(private val context: Context) : Interceptor {
    private val HEADER_TOKEN = "token"

    override fun intercept(chain: Interceptor.Chain): Response {
        val modRequest = chain.request().newBuilder()
        val tokenAvailable = SharedPreference.isAuthTokenExists(context)
        if(tokenAvailable){
            modRequest.addHeader(HEADER_TOKEN, "Bearer " + SharedPreference.initialize(context).getString(Extras.AUTH_TOKEN, "")
        }
        return chain.proceed(modRequest.build())
    }
}

手动添加header而不调用header拦截器class函数,在RetrofitClient.kt文件

kHttpClient.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();

我找到了解决我长时间面临的问题的方法。

我在 header 的键名中犯了一个愚蠢的错误。它应该是 Authorization 但一直保持为 token.

非常感谢所有试图帮助我的人。