【實戰】OKhttp通過POST提交json數據,打印請求用的攔截器

作者: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即可

使用效果:

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章