OkHttp3 Interceptor将字段添加到请求正文

时间:2019-06-09 15:13:50

标签: android kotlin retrofit interceptor okhttp3

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

这是我的retrofitBuilder:

Fax #: <input type="number" name="fax" min="1000000000" max="9999999999" required />

这是拦截器:

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

    }

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

5 个答案:

答案 0 :(得分: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;
}

}

答案 1 :(得分:0)

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

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

也许您还想添加日志记录:

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

答案 2 :(得分:0)

尽管我做了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);
         }

答案 3 :(得分:0)

对不起,没有足够的声誉来发表评论。

关于Rodrigo Queiroz的回答: In可以实际使用,但是有一些问题需要解决。

  1. 万一将Interceptor附加为Network Interceptor,它将无法正常工作,因为主体将采用gzip编码。
  2. 添加内容是否为UTF-8编码也没有意义,以拦截二进制文件。
  3. 显然,您还需要添加一些条件逻辑(如果某些时候应该跳过某些json?)
  4. 通常,整个情况很容易出错,以后可能会导致许多副作用。

    我建议考虑其他方法来完成这项工作。据我所知,如果您需要为每个Json添加一些字段,那么使用一些自定义JsonWriter / JsonConverter来简化序列化过程中的对象可能会容易得多。恕我直言,流程类似于:拦截/解码/解串/修改/序列化/编码+所有极端情况下的处理听起来像是一种过大的杀伤力。

答案 4 :(得分:0)

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {  

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

        HttpUrl url = originalHttpUrl.newBuilder()
                .addQueryParameter("apikey", "your-actual-api-key")
                .build();

        // Request customization: add request headers
        Request.Builder requestBuilder = original.newBuilder()
                .url(url);

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

访问https://futurestud.io/tutorials/retrofit-2-how-to-add-query-parameters-to-every-request