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