3

As my APIs requests all contains some json fields in common, I would like to add those fields inside an interceptor, but I'm struggling to modify the OkHttp3 RequestBody inside the interceptor

Here is my retrofitBuilder:

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

    }

And here is the interceptor:

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

How can I add, for example "traceId" : "abc123" to all my requests body inside the Interceptor?

Stack Diego
  • 1,309
  • 17
  • 43

3 Answers3

2

In my case:

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;
    }
}
djzhao
  • 934
  • 10
  • 9
0

Interceptor with header and body modification:

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

Perhaps you also want to add 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()
Rodrigo Queiroz
  • 2,674
  • 24
  • 30
  • 1
    Nope, this is adding headers.. I asked for adding fields to the body – Stack Diego Jun 09 '19 at 15:49
  • Sorry, @StackDiego I've updated the post to include the body modification. – Rodrigo Queiroz Jun 09 '19 at 16:12
  • Not working sorry, I think there is no way of achieving that without using a buffer to convert RequestBody to a string as suggested in https://stackoverflow.com/questions/34791244/retrofit2-modifying-request-body-in-okhttp-interceptor. And it could be an overkill actually – Stack Diego Jun 10 '19 at 14:01
  • Hey, @StackDiego I've got this working, hope it helps fully tested. – Rodrigo Queiroz Jun 10 '19 at 21:16
-1

This should work though i did it java, think it u should work it out in 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);
         }
Barungi Stephen
  • 759
  • 8
  • 13