【问题标题】:OkHttp3 Interceptor add fields to request bodyOkHttp3 拦截器向请求正文添加字段
【发布时间】:2019-10-24 05:27:10
【问题描述】:

由于我的 API 请求都包含一些共同的 json 字段,我想在拦截器中添加这些字段,但我正在努力修改拦截器中的 OkHttp3 RequestBody

这是我的改造构建器:

private val retrofitBuilder by lazy {


        val client = OkHttpClient.Builder().apply {
            addInterceptor(MyInterceptor())
        }.build()

        Retrofit.Builder()
            .baseUrl("https://placeholder.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build()

    }

这里是拦截器:

class MyInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {

        //Is it possible to change it in JSON? Or how do I add paramenters to this body?
        val body: RequestBody? = chain.request().body()

        return chain.proceed(chain.request())
    }
}

如何将“traceId”:“abc123”添加到拦截器内的所有请求正文中?

【问题讨论】:

标签: android kotlin retrofit interceptor okhttp3


【解决方案1】:

就我而言:

public class MyInterceptor implements Interceptor {

@Override
public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    request = addHeaderFields(request);
    request = modifyRequestBody(request);
    return chain.proceed(request);
}

/**
 * add new Headers
 */
private Request addHeaderFields(Request request) {
    return request.newBuilder()
            .addHeader("timestamp", String.valueOf(new Date().getTime()))
            .addHeader("os", "android")
            .build();
}

/**
 * add new post fields
 */
private Request modifyRequestBody(Request request) {
    if ("POST".equals(request.method())) {
        if (request.body() instanceof FormBody) {
            FormBody.Builder bodyBuilder = new FormBody.Builder();
            FormBody formBody = (FormBody) request.body();
            // Copy the original parameters first
            for (int i = 0; i < formBody.size(); i++) {
                bodyBuilder.addEncoded(formBody.encodedName(i), formBody.encodedValue(i));
            }
            // Add common parameters
            formBody = bodyBuilder
                    .addEncoded("userid", "001")
                    .addEncoded("param2", "value2")
                    .build();
            request = request.newBuilder().post(formBody).build();
        }
    }
    return request;
}

}

【讨论】:

    【解决方案2】:

    带有头部和正文修改的拦截器:

    class OkHttpInterceptor() : Interceptor {
    
        override fun intercept(chain: Interceptor.Chain): Response {
            val request = chain.request()
            val requestWithAndroidHeaders = addHeaderFields(request)
            val response = chain.proceed(requestWithAndroidHeaders)
            return modifyResponseBody(response)
        }
    
        private fun addHeaderFields(request: Request): Request = request.newBuilder()
                    .addHeader("Content-Type", "application/json")
                    .addHeader("User-Agent", "Android")
                    .addHeader("TraceId", "abc 123")
                    .build()
    
        private fun modifyResponseBody(response: Response): Response {
            val responseString = response.body()?.charStream()?.readText()
            val responseJson = responseString?.let { stringToJson(it) }
            return if (responseJson != null) {
                val contentType: MediaType? = response.body()?.contentType()
                val responseBody = ResponseBody.create(contentType, responseJson.toString())
                response.newBuilder().body(responseBody).build()
            } else {
               response
            }
        }
    
        private fun stringToJson(responseString: String): JSONObject? = try {
            JSONObject(responseString).put("traceId", "abc 123")
        } catch (e: JSONException) {
            println(e.message)
            null
        }
    }
    

    OkHttpClient:

    val okHttpInterceptor = OkHttpInterceptor()
    val client = OkHttpClient.Builder()
    client.interceptors().add(okHttpInterceptor)
    client.build()
    

    也许您还想添加 Logging:

    val logging = HttpLoggingInterceptor()
    if(BuildConfig.DEBUG) {
        logging.level = HttpLoggingInterceptor.Level.BODY
    } else {
        logging.level = HttpLoggingInterceptor.Level.NONE
    }
    val okHttpInterceptor = OkHttpInterceptor()
    val client = OkHttpClient.Builder()
    client.interceptors().add(okHttpInterceptor)
    client.interceptors().add(logging)
    client.build()
    

    【讨论】:

    • 不,这是添加标题.. 我要求在正文中添加字段
    • 抱歉,@StackDiego 我已经更新了帖子以包含正文修改。
    • 不工作对不起,我认为如果不使用缓冲区将 RequestBody 转换为stackoverflow.com/questions/34791244/… 中建议的字符串,就无法实现这一目标。实际上这可能是一种矫枉过正
    • 嘿,@StackDiego 我已经完成了这项工作,希望它对全面测试有所帮助。
    【解决方案3】:

    这应该可以,虽然我是用 java 做的,但认为你应该在 kotlin 中解决它

    public Response intercept(@NonNull Chain chain) throws IOException {
                 Request original = chain.request();
                 // Request customization: add request headers
                 Request.Builder requestBuilder = original.newBuilder();
                 //requestBuilder.addHeader("key",API_KEY);
                 requestBuilder.addHeader("Content-Type","application/json");
    
                 Request request = requestBuilder.build();
                 return chain.proceed(request);
             }
    

    【讨论】:

    • 这是添加标头,而不是更改请求负载
    • 您想将该参数添加到所有 POST 、 GET 、 PUT 等请求中吗?
    • 如果它是相同类型的请求,例如 POST,Paherps,您应该创建一个单例,其中所有请求都预先附加您的参数
    猜你喜欢
    • 2017-03-08
    • 2016-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 2016-04-19
    • 2020-06-23
    • 2015-11-18
    相关资源
    最近更新 更多