作者:DCTANT
寫作背景:網上到處都是用OKhttp配合Retrofit使用Json通過POST提交數據,但是攔截器一個都沒有, 坑得要死,還有一篇介紹POST請求用的攔截器的,結果用了發現對json POST數據來說一點用處沒有。
爲了與時俱進,代碼全是用Kotlin寫的,畢竟OKhttp4.0也是用Kotlin寫的了(覺得不爽來打我啊!O(∩_∩)O哈哈~),主要參考
HttpLoggingInterceptor寫的,不然根本寫不出來,畢竟RequestBody打斷點,能看得見content,就是拿不出來,看得見摸不着,費了我好長時間,最後發現源碼中的HTTPLoggingInterceptor用requestBody.writeTo就解決了這個問題,後悔當時沒早點看源碼。
下面上代碼:
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
import java.nio.charset.Charset
import java.util.concurrent.TimeUnit
class PostInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response? {
val request = chain.request()
//打印請求起始信息
val requestStartMsg = "--> ${request.method()} ${request.url()} ${request.body()?.contentLength()}-byte body"
println(requestStartMsg)
request.body()?.also { requestBody ->
val bodyString = "Content-Type: ${requestBody.contentType()} Content-Length: ${requestBody.contentLength()}"
println(bodyString)
}
val requestHeaders = request.headers()
val size = requestHeaders.size()
//打印請求頭信息
for (i in 0 until size) {
val name = requestHeaders.name(i)
if (!"Content-Type".equals(name, true) && !"Content-Length".equals(name, true)) {
println("${name} : ${requestHeaders.value(i)}")
}
}
val requestBody = request.body()
val buffer = Buffer()
//將請求體內容寫入buffer中
requestBody?.writeTo(buffer)
println()
//打印整個請求體中的內容(這步全靠打斷點找出來的)
println(buffer.readByteString().utf8())
println("--> END ${request.method()} (${requestBody?.contentLength()}-byte body)")
val startNs = System.nanoTime()
//執行請求
val response = chain.proceed(request)
//計算耗時
val tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs)
requestBody?.also { requestBody ->
//請求完成後打印請求信息
val bodyInfo = "<-- ${response.code()} ${response.message()} ${response.request().url()} (${tookMs} ms) Content-Length ${requestBody.contentLength()}"
println(bodyInfo)
} ?: also {
println("No request body found!!")
}
val responseHeaders = response.headers()
//打印Response頭中的信息
for (i in 0 until requestHeaders.size()) {
println("${responseHeaders.name(i)} : ${responseHeaders.value(i)}")
}
response.body()?.also { responseBody ->
val source = responseBody.source()
source.request(Long.MAX_VALUE)
val sourceBuffer = source.buffer()
//打印Response中的內容(如果直接用responseBody.string()會導致流關閉而報錯!java.lang.IllegalStateException: closed)
println(sourceBuffer.clone().readString(Charset.defaultCharset()))
println("<-- END HTTP (${sourceBuffer.size()} -byte body)")
} ?: also {
println("<-- END HTTP No response body found!")
}
return response
}
}
使用:OKhttpClient.Builder()的時候addInterceptor中new 一個PostInterceptor即可
使用效果: