OkHttp3 Interceptor добавляет поля в тело запроса - PullRequest
0 голосов
/ 09 июня 2019

Поскольку все мои запросы API содержат некоторые общие поля json, я хотел бы добавить эти поля внутри перехватчика, но я пытаюсь изменить OkBttp3 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» ко всем моим телам запросов внутри Interceptor?

Ответы [ 3 ]

0 голосов
/ 09 июня 2019

Это должно работать, хотя я сделал это 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);
         }
0 голосов
/ 15 июня 2019

Извините, у вас недостаточно репутации, чтобы комментировать.

По поводу ответа Родриго Кейроз : Может действительно работать, но есть некоторые проблемы, которые имеет смысл решать.

  1. Это не будет работать должным образом, если Interceptor будет присоединен как Network Interceptor, так как тело будет закодировано в gzip.
  2. Также имеет смысл добавить проверку, если контент имеет кодировку UTF-8, нет, чтобы перехватывать двоичные файлы.
  3. Очевидно, вам также необходимо добавить некоторую условную логику (если какой-то json должен быть пропущен в определенный момент?)
  4. В целом весь этот сценарий очень подвержен ошибкам и может вызвать многочисленные побочные эффекты в дальнейшем.

    Я бы предложил подумать о другом способе выполнения работы. По моему мнению, если вам нужно добавить некоторые поля к каждому отдельному Json, вероятно, будет гораздо проще использовать вместо этого какой-нибудь пользовательский JsonWriter / JsonConverter, чтобы изменить ваши объекты во время сериализации за один простой шаг. ИМХО, Flow как: перехватывать / декодировать / десериализовать / модифицировать / сериализовать / кодировать + обработка всех угловых случаев звучит как чистое излишество.

0 голосов
/ 09 июня 2019

Перехватчик с модификацией заголовка и тела:

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