Модернизация Android — перехватывать все запросы GET / PUT / POST / DELETE

#android #kotlin #http-post #retrofit2 #interceptor

#Android #kotlin #http-post #модернизация 2 #перехватчик

Вопрос:

Приветствую всех коллег-разработчиков. У меня есть приложение, которое уже опубликовано в playstore и использует модернизацию в качестве сетевого интерфейса. Теперь я столкнулся с требованием, в котором я должен отправлять параметр во всех запросах, проходящих через приложение, независимо от того, является ли запрос GET / PUT / POST / DELETE . В случае GET / PUT / DELETE я отправляю дополнительный параметр в качестве параметра запроса, но в POST я добавляю это в тело. Смотрите код ниже —

 class CommonParamsInterceptor : Interceptor {
companion object {
    const val EXTRA_PARAM = "extra_param"
}

override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    return chain.proceed(
                when (request.method()) {
                    HTTP_METHOD_GET, HTTP_METHOD_PUT, HTTP_METHOD_DELETE -> {
                        val url = request.url()
                        request.newBuilder()
                            .url(
                                url.newBuilder()
                                    .addQueryParameter(EXTRA_PARAM, "param_value")
                                    .build()
                            )
                            .build()
                    }
                    HTTP_METHOD_POST -> {
                        val body = request.body()
                        request.newBuilder()
                            .post(
                                RequestBody.create(
                                    body?.contentType(),
                                    body.bodyToString()   "amp;"   EXTRA_PARAM   "="   "param_value"
                                )
                            )
                            .build()
                    }
                    else -> request
                }
            )
        }
    }




private fun RequestBody?.bodyToString(): String {
    if (this == null) return ""
    val buffer = okio.Buffer()
    writeTo(buffer)
    return buffer.readUtf8()
}
  

Теперь проблема в том, что некоторые из моих запросов post могут не иметь тела или могут иметь карту или могут иметь json в качестве содержимого. Итак, как добавить ПАРАМЕТР во все запросы post независимо от типа тела?. Заранее спасибо.

Комментарии:

1. Это действительно зависит от того, что ожидает получить ваш сервер, нет единого способа добавить часть данных к любому типу тела.

Ответ №1:

Для дальнейшего использования публикую свою версию решения.

 class CommonParamsInterceptor : Interceptor {
companion object {
    const val PARAM_EXTRA = "extra_param"
    const val TYPE_FORM = "form"
    const val TYPE_JSON = "json"
}

override fun intercept(chain: Interceptor.Chain): Response {
    val request = chain.request()
    return  chain.proceed(
                when (request.method()) {
                    HTTP_METHOD_GET, HTTP_METHOD_PUT, HTTP_METHOD_DELETE -> {
                        val url = request.url()
                        request.newBuilder()
                            .url(
                                url.newBuilder()
                                    .addQueryParameter(PARAM_EXTRA, "val")
                                    .build()
                            )
                            .build()
                    }
                    HTTP_METHOD_POST -> {
                        var requestBody = request.body()
                        if (requestBody != null) {
                            val subtype = requestBody.contentType()?.subtype()
                            if (subtype?.contains(TYPE_JSON) == true) { /* when it is json */
                                requestBody = processApplicationJsonRequestBody(requestBody)
                            } else if (subtype?.contains(TYPE_FORM) == true) { /* when it is form-data */
                                requestBody = processFormDataRequestBody(requestBody)
                            }
                        } else { /* when we don't have any body*/
                            requestBody = FormBody.Builder()
                                .add(PARAM_EXTRA, "val")
                                .build()
                        }
                        requestBody?.run {
                            request.newBuilder()
                                .post(this)
                                .build()
                        } ?: kotlin.run {
                            request
                        }
                    }

                    else -> request
                }
            )
    }
}

private fun bodyToString(request: RequestBody?): String {
    if (request == null) return ""
    try {
        val buffer = okio.Buffer()
        request.writeTo(buffer)
        return buffer.readUtf8()
    } catch (e: Exception) {
        MerchantLogger.logAndPrintException(e)
        return ""
    }
}

private fun processApplicationJsonRequestBody(
    requestBody: RequestBody
): RequestBody? {
    val customReq = bodyToString(requestBody)
    try {
        val obj = JSONObject(customReq)
        obj.put(PARAM_EXTRA, "val")
        return RequestBody.create(requestBody.contentType(), obj.toString())
    } catch (e: JSONException) {
        e.printStackTrace()
    }
    return null
}

private fun processFormDataRequestBody(
    requestBody: RequestBody
): RequestBody {
    val formBody: RequestBody = FormBody.Builder()
        .add(PARAM_EXTRA,"val")
        .build()
    var postBodyString = bodyToString(requestBody)
    postBodyString  = (if (postBodyString.isEmpty().not()) "amp;" else "")   bodyToString(formBody)
    return RequestBody.create(requestBody.contentType(), postBodyString)
}
  }