|
23 | 23 | */
|
24 | 24 | package com.owncloud.android.lib.common.http
|
25 | 25 |
|
| 26 | +import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID |
26 | 27 | import com.owncloud.android.lib.common.http.LogBuilder.logHttp
|
27 | 28 | import com.owncloud.android.lib.common.http.NetworkNode.BODY
|
28 | 29 | import com.owncloud.android.lib.common.http.NetworkNode.HEADER
|
29 | 30 | import com.owncloud.android.lib.common.http.NetworkNode.INFO
|
30 | 31 | import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST
|
31 | 32 | import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE
|
| 33 | +import okhttp3.Headers |
32 | 34 | import okhttp3.Interceptor
|
| 35 | +import okhttp3.RequestBody |
33 | 36 | import okhttp3.Response
|
| 37 | +import okhttp3.ResponseBody |
| 38 | +import okio.Buffer |
| 39 | +import java.nio.charset.Charset |
| 40 | +import java.nio.charset.StandardCharsets |
| 41 | +import kotlin.math.max |
34 | 42 |
|
35 | 43 | class LogInterceptor : Interceptor {
|
36 | 44 |
|
37 | 45 | override fun intercept(chain: Interceptor.Chain): Response {
|
38 | 46 |
|
39 |
| - val response = chain.proceed(chain.request()) |
| 47 | + if (!httpLogsEnabled) { |
| 48 | + return chain.proceed(chain.request()) |
| 49 | + } |
| 50 | + |
| 51 | + val request = chain.request().also { |
| 52 | + val requestId = it.headers[OC_X_REQUEST_ID] |
| 53 | + logHttp(REQUEST, INFO, requestId, "Type: ${it.method} URL: ${it.url}") |
| 54 | + logHeaders(requestId, it.headers, REQUEST) |
| 55 | + logRequestBody(requestId, it.body) |
| 56 | + } |
| 57 | + |
| 58 | + val response = chain.proceed(request) |
40 | 59 |
|
41 | 60 | return response.also {
|
42 |
| - if (httpLogsEnabled) { |
43 |
| - // Log request |
44 |
| - logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") |
45 |
| - it.request.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } |
46 |
| - logHttp(REQUEST, BODY, it.request.body.toString()) |
47 |
| - |
48 |
| - // Log response |
49 |
| - logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") |
50 |
| - it.headers.forEach { header -> logHttp(RESPONSE, HEADER, header.toString()) } |
51 |
| - logHttp(RESPONSE, BODY, it.body.toString()) |
52 |
| - } |
| 61 | + val requestId = it.request.headers[OC_X_REQUEST_ID] |
| 62 | + logHttp( |
| 63 | + RESPONSE, |
| 64 | + INFO, |
| 65 | + requestId, |
| 66 | + "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" |
| 67 | + ) |
| 68 | + logHeaders(requestId, it.headers, RESPONSE) |
| 69 | + logResponseBody(requestId, it.body) |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) { |
| 74 | + headers.forEach { header -> |
| 75 | + logHttp(networkPetition, HEADER, requestId, "${header.first}: ${header.second}") |
53 | 76 | }
|
54 | 77 | }
|
55 | 78 |
|
| 79 | + private fun logRequestBody(requestId: String?, requestBodyParam: RequestBody?) { |
| 80 | + requestBodyParam?.let { requestBody -> |
| 81 | + |
| 82 | + if (requestBody.isOneShot()) { |
| 83 | + logHttp(REQUEST, BODY, requestId, "One shot body -- Omitted") |
| 84 | + return@let |
| 85 | + } |
| 86 | + |
| 87 | + if (requestBody.isDuplex()) { |
| 88 | + logHttp(REQUEST, BODY, requestId, "Duplex body -- Omitted") |
| 89 | + return@let |
| 90 | + } |
| 91 | + |
| 92 | + val buffer = Buffer() |
| 93 | + requestBody.writeTo(buffer) |
| 94 | + |
| 95 | + val contentType = requestBody.contentType() |
| 96 | + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 |
| 97 | + |
| 98 | + logHttp(REQUEST, BODY, requestId, "Length: ${requestBody.contentLength()} byte body") |
| 99 | + logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}") |
| 100 | + logHttp(REQUEST, BODY, requestId, "--> Body start for request") |
| 101 | + |
| 102 | + if (buffer.isProbablyUtf8()) { |
| 103 | + if (requestBody.contentLength() < LIMIT_BODY_LOG) { |
| 104 | + logHttp(REQUEST, BODY, requestId, buffer.readString(charset)) |
| 105 | + } else { |
| 106 | + logHttp(REQUEST, BODY, requestId, buffer.readString(LIMIT_BODY_LOG, charset)) |
| 107 | + } |
| 108 | + logHttp( |
| 109 | + REQUEST, |
| 110 | + BODY, |
| 111 | + requestId, |
| 112 | + "<-- Body end for request -- Omitted: ${max(0, requestBody.contentLength() - LIMIT_BODY_LOG)} bytes" |
| 113 | + ) |
| 114 | + } else { |
| 115 | + logHttp( |
| 116 | + REQUEST, |
| 117 | + BODY, |
| 118 | + requestId, |
| 119 | + "<-- Body end for request -- Binary -- Omitted: ${requestBody.contentLength()} bytes" |
| 120 | + ) |
| 121 | + } |
| 122 | + |
| 123 | + } ?: logHttp(REQUEST, BODY, requestId, "Empty body") |
| 124 | + } |
| 125 | + |
| 126 | + private fun logResponseBody(requestId: String?, responseBodyParam: ResponseBody?) { |
| 127 | + responseBodyParam?.let { responseBody -> |
| 128 | + |
| 129 | + val contentType = responseBody.contentType() |
| 130 | + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 |
| 131 | + |
| 132 | + logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body") |
| 133 | + logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}") |
| 134 | + logHttp(RESPONSE, BODY, requestId, "--> Body start for request") |
| 135 | + |
| 136 | + val source = responseBody.source() |
| 137 | + source.request(LIMIT_BODY_LOG) |
| 138 | + val buffer = source.buffer |
| 139 | + |
| 140 | + if (!buffer.isProbablyUtf8()) { |
| 141 | + logHttp( |
| 142 | + REQUEST, |
| 143 | + BODY, |
| 144 | + requestId, |
| 145 | + "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" |
| 146 | + ) |
| 147 | + } |
| 148 | + |
| 149 | + if (responseBody.contentLength() < LIMIT_BODY_LOG) { |
| 150 | + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(charset)) |
| 151 | + } else { |
| 152 | + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) |
| 153 | + } |
| 154 | + logHttp( |
| 155 | + REQUEST, |
| 156 | + BODY, |
| 157 | + requestId, |
| 158 | + "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" |
| 159 | + ) |
| 160 | + } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") |
| 161 | + } |
| 162 | + |
56 | 163 | companion object {
|
57 | 164 | var httpLogsEnabled: Boolean = false
|
| 165 | + private const val LIMIT_BODY_LOG: Long = 1024 |
58 | 166 | }
|
59 | 167 | }
|
0 commit comments