From 775fdb080cc3deb7b628925f77870060e1eb0cf3 Mon Sep 17 00:00:00 2001 From: agarcia Date: Wed, 30 Sep 2020 16:43:38 +0200 Subject: [PATCH 01/14] Add first draft to log network calls --- .../android/lib/common/http/HttpClient.java | 9 +++ .../android/lib/common/http/LogBuilder.kt | 39 +++++++++++++ .../android/lib/common/http/LogInterceptor.kt | 57 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 12571a88..517dd56a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -57,6 +57,7 @@ public class HttpClient { private static OkHttpClient sOkHttpClient; private static Context sContext; private static HashMap> sCookieStore = new HashMap<>(); + private static LogInterceptor sLogInterceptor; public static OkHttpClient getOkHttpClient() { if (sOkHttpClient == null) { @@ -111,6 +112,7 @@ public class HttpClient { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .protocols(Arrays.asList(Protocol.HTTP_1_1)) + .addInterceptor(getLogInterceptor()) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) @@ -137,6 +139,13 @@ public class HttpClient { sContext = context; } + public static LogInterceptor getLogInterceptor() { + if (sLogInterceptor == null) { + sLogInterceptor = new LogInterceptor(); + } + return sLogInterceptor; + } + public List getCookiesFromUrl(HttpUrl httpUrl) { return sCookieStore.get(httpUrl.host()); } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt new file mode 100644 index 00000000..ef9df143 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -0,0 +1,39 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2020 ownCloud GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.owncloud.android.lib.common.http + +object LogBuilder { + fun toLogString( + networkPetition: NetworkPetition, + networkNode: NetworkNode, + description: String + ): String = "[Network, $networkPetition] [$networkNode] $description" +} + +enum class NetworkPetition { + REQUEST, RESPONSE +} + +enum class NetworkNode { + INFO, HEADER, BODY +} diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt new file mode 100644 index 00000000..89fa09bd --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -0,0 +1,57 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2020 ownCloud GmbH. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ +package com.owncloud.android.lib.common.http + +import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import okhttp3.Interceptor +import okhttp3.Response +import timber.log.Timber + +class LogInterceptor : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + // Log request + chain.request().let { + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.INFO, "Type: ${it.method} URL: ${it.url}")) + it.headers.forEach { header -> + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.HEADER, header.toString())) + } + Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.BODY, it.body.toString())) + } + + val response = chain.proceed(chain.request()) + + // Log response + response.let { + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}")) + it.headers.forEach { header -> + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.HEADER, header.toString())) + } + Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.BODY, it.body.toString())) + } + + return response + } +} From a564f18f161a0079a83835577d22ab73491a64d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Fri, 2 Oct 2020 14:38:38 +0200 Subject: [PATCH 02/14] Http logs enabled only in debug versions --- .../com/owncloud/android/lib/common/http/HttpClient.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 517dd56a..9aab751a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -26,6 +26,7 @@ package com.owncloud.android.lib.common.http; import android.content.Context; +import com.owncloud.android.lib.BuildConfig; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.NetworkUtils; import okhttp3.Cookie; @@ -112,7 +113,6 @@ public class HttpClient { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() .protocols(Arrays.asList(Protocol.HTTP_1_1)) - .addInterceptor(getLogInterceptor()) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .connectTimeout(HttpConstants.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS) @@ -122,6 +122,12 @@ public class HttpClient { .cookieJar(cookieJar); // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); + + // Http logs enabled only in debug version. TODO: Add an option to enable and disable it. + if (BuildConfig.DEBUG) { + clientBuilder.addInterceptor(getLogInterceptor()); + } + sOkHttpClient = clientBuilder.build(); } catch (Exception e) { From dc215dc80e344dd93b42109dceacf352c3e8d21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Mon, 5 Oct 2020 13:19:38 +0200 Subject: [PATCH 03/14] Add a new variable to enable or disable http logs --- .../android/lib/common/http/LogInterceptor.kt | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 89fa09bd..400b6120 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -24,6 +24,8 @@ package com.owncloud.android.lib.common.http import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import com.owncloud.android.lib.common.http.NetworkNode.* +import com.owncloud.android.lib.common.http.NetworkPetition.* import okhttp3.Interceptor import okhttp3.Response import timber.log.Timber @@ -31,27 +33,39 @@ import timber.log.Timber class LogInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { - // Log request - chain.request().let { - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.INFO, "Type: ${it.method} URL: ${it.url}")) - it.headers.forEach { header -> - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.HEADER, header.toString())) - } - Timber.d(toLogString(NetworkPetition.REQUEST, NetworkNode.BODY, it.body.toString())) - } val response = chain.proceed(chain.request()) - // Log response - response.let { - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}")) - it.headers.forEach { header -> - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.HEADER, header.toString())) - } - Timber.d(toLogString(NetworkPetition.RESPONSE, NetworkNode.BODY, it.body.toString())) - } + return response.also { + if (httpLogsEnabled) { + // Log request + Timber.d( + toLogString(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") + ) + it.headers.forEach { header -> + Timber.d(toLogString(REQUEST, HEADER, header.toString())) + } + Timber.d(toLogString(REQUEST, BODY, it.body.toString())) - return response + // Log response + Timber.d(toLogString(RESPONSE, INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) + Timber.d( + toLogString( + RESPONSE, + INFO, + "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" + ) + ) + it.headers.forEach { header -> + Timber.d(toLogString(RESPONSE, HEADER, header.toString())) + } + Timber.d(toLogString(RESPONSE, BODY, it.body.toString())) + + } + } + } + + companion object { + var httpLogsEnabled: Boolean = false } } From b7fd663d77efab4b529c870e3de18d980a501d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Mon, 5 Oct 2020 14:27:26 +0200 Subject: [PATCH 04/14] Improve http logs --- .../android/lib/common/http/LogBuilder.kt | 15 +++++++--- .../android/lib/common/http/LogInterceptor.kt | 29 +++++-------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index ef9df143..7cf6ef28 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -22,18 +22,25 @@ */ package com.owncloud.android.lib.common.http +import timber.log.Timber +import java.util.Locale + object LogBuilder { - fun toLogString( + fun logHttp( networkPetition: NetworkPetition, networkNode: NetworkNode, description: String - ): String = "[Network, $networkPetition] [$networkNode] $description" + ) = Timber.d("[Network, $networkPetition] [$networkNode] $description") } enum class NetworkPetition { - REQUEST, RESPONSE + REQUEST, RESPONSE; + + override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } enum class NetworkNode { - INFO, HEADER, BODY + INFO, HEADER, BODY; + + override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 400b6120..403b277a 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,12 +23,11 @@ */ package com.owncloud.android.lib.common.http -import com.owncloud.android.lib.common.http.LogBuilder.toLogString +import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.* import com.owncloud.android.lib.common.http.NetworkPetition.* import okhttp3.Interceptor import okhttp3.Response -import timber.log.Timber class LogInterceptor : Interceptor { @@ -39,28 +38,14 @@ class LogInterceptor : Interceptor { return response.also { if (httpLogsEnabled) { // Log request - Timber.d( - toLogString(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - ) - it.headers.forEach { header -> - Timber.d(toLogString(REQUEST, HEADER, header.toString())) - } - Timber.d(toLogString(REQUEST, BODY, it.body.toString())) + logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") + it.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } + logHttp(REQUEST, BODY, it.body.toString()) // Log response - Timber.d(toLogString(RESPONSE, INFO, "RequestId: ${it.request.header(HttpConstants.OC_X_REQUEST_ID)}")) - Timber.d( - toLogString( - RESPONSE, - INFO, - "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" - ) - ) - it.headers.forEach { header -> - Timber.d(toLogString(RESPONSE, HEADER, header.toString())) - } - Timber.d(toLogString(RESPONSE, BODY, it.body.toString())) - + logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") + it.headers.forEach { header -> logHttp(RESPONSE, HEADER, header.toString()) } + logHttp(RESPONSE, BODY, it.body.toString()) } } } From dc3947576064f6c749888cd0136cbedec33a94a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 13 Oct 2020 08:52:04 +0200 Subject: [PATCH 05/14] Add log interceptor disabled by default --- .../com/owncloud/android/lib/common/http/HttpClient.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 9aab751a..574b5539 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -26,7 +26,6 @@ package com.owncloud.android.lib.common.http; import android.content.Context; -import com.owncloud.android.lib.BuildConfig; import com.owncloud.android.lib.common.network.AdvancedX509TrustManager; import com.owncloud.android.lib.common.network.NetworkUtils; import okhttp3.Cookie; @@ -112,6 +111,7 @@ public class HttpClient { }; OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() + .addInterceptor(getLogInterceptor()) .protocols(Arrays.asList(Protocol.HTTP_1_1)) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) @@ -123,11 +123,6 @@ public class HttpClient { // TODO: Not verifying the hostname against certificate. ask owncloud security human if this is ok. //.hostnameVerifier(new BrowserCompatHostnameVerifier()); - // Http logs enabled only in debug version. TODO: Add an option to enable and disable it. - if (BuildConfig.DEBUG) { - clientBuilder.addInterceptor(getLogInterceptor()); - } - sOkHttpClient = clientBuilder.build(); } catch (Exception e) { From aa665a7295e53468d8e354a22c8c268e2eef55d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 20 Oct 2020 11:31:52 +0200 Subject: [PATCH 06/14] Show request headers and body properly --- .../android/lib/common/http/LogInterceptor.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 403b277a..9aad57a2 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -24,8 +24,11 @@ package com.owncloud.android.lib.common.http import com.owncloud.android.lib.common.http.LogBuilder.logHttp -import com.owncloud.android.lib.common.http.NetworkNode.* -import com.owncloud.android.lib.common.http.NetworkPetition.* +import com.owncloud.android.lib.common.http.NetworkNode.BODY +import com.owncloud.android.lib.common.http.NetworkNode.HEADER +import com.owncloud.android.lib.common.http.NetworkNode.INFO +import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST +import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE import okhttp3.Interceptor import okhttp3.Response @@ -39,8 +42,8 @@ class LogInterceptor : Interceptor { if (httpLogsEnabled) { // Log request logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - it.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } - logHttp(REQUEST, BODY, it.body.toString()) + it.request.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } + logHttp(REQUEST, BODY, it.request.body.toString()) // Log response logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") From c0d2e20bb147f3234de5dd56838229fd38869364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 15:39:48 +0200 Subject: [PATCH 07/14] Log http body if it is not binary --- .../android/lib/common/http/LogBuilder.kt | 3 +- .../android/lib/common/http/LogInterceptor.kt | 132 ++++++++++++++++-- .../owncloud/android/lib/common/http/utf8.kt | 44 ++++++ 3 files changed, 166 insertions(+), 13 deletions(-) create mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index 7cf6ef28..c85f4fd5 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -29,8 +29,9 @@ object LogBuilder { fun logHttp( networkPetition: NetworkPetition, networkNode: NetworkNode, + requestId: String? = "", description: String - ) = Timber.d("[Network, $networkPetition] [$networkNode] $description") + ) = Timber.d("[Network, $networkPetition] [$networkNode] [$requestId] $description") } enum class NetworkPetition { diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 9aad57a2..0877deca 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,37 +23,145 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.BODY import com.owncloud.android.lib.common.http.NetworkNode.HEADER import com.owncloud.android.lib.common.http.NetworkNode.INFO import com.owncloud.android.lib.common.http.NetworkPetition.REQUEST import com.owncloud.android.lib.common.http.NetworkPetition.RESPONSE +import okhttp3.Headers import okhttp3.Interceptor +import okhttp3.RequestBody import okhttp3.Response +import okhttp3.ResponseBody +import okio.Buffer +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets +import kotlin.math.max class LogInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { - val response = chain.proceed(chain.request()) + if (!httpLogsEnabled) { + return chain.proceed(chain.request()) + } + + val request = chain.request().also { + val requestId = it.headers[OC_X_REQUEST_ID] + logHttp(REQUEST, INFO, requestId, "Type: ${it.method} URL: ${it.url}") + logHeaders(requestId, it.headers, REQUEST) + logRequestBody(requestId, it.body) + } + + val response = chain.proceed(request) return response.also { - if (httpLogsEnabled) { - // Log request - logHttp(REQUEST, INFO, "Type: ${it.request.method} URL: ${it.request.url}") - it.request.headers.forEach { header -> logHttp(REQUEST, HEADER, header.toString()) } - logHttp(REQUEST, BODY, it.request.body.toString()) - - // Log response - logHttp(RESPONSE, INFO, "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}") - it.headers.forEach { header -> logHttp(RESPONSE, HEADER, header.toString()) } - logHttp(RESPONSE, BODY, it.body.toString()) - } + val requestId = it.request.headers[OC_X_REQUEST_ID] + logHttp( + RESPONSE, + INFO, + requestId, + "Code: ${it.code} Message: ${it.message} IsSuccessful: ${it.isSuccessful}" + ) + logHeaders(requestId, it.headers, RESPONSE) + logResponseBody(requestId, it.body) } } + private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) { + headers.forEach { header -> + logHttp(networkPetition, HEADER, requestId, "${header.first}: ${header.second}") + } + } + + private fun logRequestBody(requestId: String?, requestBodyParam: RequestBody?) { + requestBodyParam?.let { requestBody -> + + if (requestBody.isOneShot()) { + logHttp(REQUEST, BODY, requestId, "One shot body -- Omitted") + return@let + } + + if (requestBody.isDuplex()) { + logHttp(REQUEST, BODY, requestId, "Duplex body -- Omitted") + return@let + } + + val buffer = Buffer() + requestBody.writeTo(buffer) + + val contentType = requestBody.contentType() + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 + + logHttp(REQUEST, BODY, requestId, "Length: ${requestBody.contentLength()} byte body") + logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}") + logHttp(REQUEST, BODY, requestId, "--> Body start for request") + + if (buffer.isProbablyUtf8()) { + if (requestBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(REQUEST, BODY, requestId, buffer.readString(charset)) + } else { + logHttp(REQUEST, BODY, requestId, buffer.readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Omitted: ${max(0, requestBody.contentLength() - LIMIT_BODY_LOG)} bytes" + ) + } else { + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Binary -- Omitted: ${requestBody.contentLength()} bytes" + ) + } + + } ?: logHttp(REQUEST, BODY, requestId, "Empty body") + } + + private fun logResponseBody(requestId: String?, responseBodyParam: ResponseBody?) { + responseBodyParam?.let { responseBody -> + + val contentType = responseBody.contentType() + val charset: Charset = contentType?.charset(StandardCharsets.UTF_8) ?: StandardCharsets.UTF_8 + + logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body") + logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}") + logHttp(RESPONSE, BODY, requestId, "--> Body start for request") + + val source = responseBody.source() + source.request(LIMIT_BODY_LOG) + val buffer = source.buffer + + if (!buffer.isProbablyUtf8()) { + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" + ) + } + + if (responseBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(charset)) + } else { + logHttp(REQUEST, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + REQUEST, + BODY, + requestId, + "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" + ) + } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") + } + companion object { var httpLogsEnabled: Boolean = false + private const val LIMIT_BODY_LOG: Long = 1024 } } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt new file mode 100644 index 00000000..9591e425 --- /dev/null +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.owncloud.android.lib.common.http + +import java.io.EOFException +import okio.Buffer + +/** + * Returns true if the body in question probably contains human readable text. Uses a small + * sample of code points to detect unicode control characters commonly used in binary file + * signatures. + */ +internal fun Buffer.isProbablyUtf8(): Boolean { + try { + val prefix = Buffer() + val byteCount = size.coerceAtMost(64) + copyTo(prefix, 0, byteCount) + for (i in 0 until 16) { + if (prefix.exhausted()) { + break + } + val codePoint = prefix.readUtf8CodePoint() + if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { + return false + } + } + return true + } catch (_: EOFException) { + return false // Truncated UTF-8 sequence. + } +} From 197c86ec64a4b68151ef74154bc6ac28df6584de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 15:59:39 +0200 Subject: [PATCH 08/14] Add LogInterceptor as NetworkInterceptor --- .../java/com/owncloud/android/lib/common/http/HttpClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java index 574b5539..06e8056d 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpClient.java @@ -111,7 +111,7 @@ public class HttpClient { }; OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() - .addInterceptor(getLogInterceptor()) + .addNetworkInterceptor(getLogInterceptor()) .protocols(Arrays.asList(Protocol.HTTP_1_1)) .readTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(HttpConstants.DEFAULT_DATA_TIMEOUT, TimeUnit.MILLISECONDS) From db97ed7fb350182756d18121b038a2f93bbdd2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 21 Oct 2020 18:21:39 +0200 Subject: [PATCH 09/14] Fix response log marked as request one --- .../owncloud/android/lib/common/http/LogInterceptor.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 0877deca..0352b821 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -139,7 +139,7 @@ class LogInterceptor : Interceptor { if (!buffer.isProbablyUtf8()) { logHttp( - REQUEST, + RESPONSE, BODY, requestId, "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" @@ -147,12 +147,12 @@ class LogInterceptor : Interceptor { } if (responseBody.contentLength() < LIMIT_BODY_LOG) { - logHttp(REQUEST, BODY, requestId, buffer.clone().readString(charset)) + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) } else { - logHttp(REQUEST, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) } logHttp( - REQUEST, + RESPONSE, BODY, requestId, "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" From 781f958c9383e2784137630df2d43c02f936e75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Fri, 23 Oct 2020 11:38:40 +0200 Subject: [PATCH 10/14] Do not log chunk request body --- .../owncloud/android/lib/common/network/FileRequestBody.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java index 2df9884d..18746ba7 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/FileRequestBody.java @@ -53,6 +53,11 @@ public class FileRequestBody extends RequestBody implements ProgressiveDataTrans mContentType = contentType; } + @Override + public boolean isOneShot() { + return true; + } + @Override public MediaType contentType() { return mContentType; From 943c5ecb97f3a4a5ee24fb9010b6d8d89fb53931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 27 Oct 2020 16:09:01 +0100 Subject: [PATCH 11/14] Fix typo --- .../com/owncloud/android/lib/common/http/LogInterceptor.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 0352b821..30860f54 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -131,7 +131,7 @@ class LogInterceptor : Interceptor { logHttp(RESPONSE, BODY, requestId, "Length: ${responseBody.contentLength()} byte body") logHttp(RESPONSE, BODY, requestId, "Type: ${responseBody.contentType()}") - logHttp(RESPONSE, BODY, requestId, "--> Body start for request") + logHttp(RESPONSE, BODY, requestId, "--> Body start for response") val source = responseBody.source() source.request(LIMIT_BODY_LOG) @@ -142,7 +142,7 @@ class LogInterceptor : Interceptor { RESPONSE, BODY, requestId, - "<-- Body end for request -- Binary -- Omitted: ${responseBody.contentLength()} bytes" + "<-- Body end for response -- Binary -- Omitted: ${responseBody.contentLength()} bytes" ) } @@ -155,7 +155,7 @@ class LogInterceptor : Interceptor { RESPONSE, BODY, requestId, - "<-- Body end for request -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" + "<-- Body end for response -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" ) } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") } From 460f85f2e175879894898f595be75a5d9588cff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Tue, 27 Oct 2020 16:12:23 +0100 Subject: [PATCH 12/14] Remove binary file logs --- .../lib/common/network/ChunkFromFileRequestBody.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java index 53abaf9a..40f168ea 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/network/ChunkFromFileRequestBody.java @@ -84,18 +84,12 @@ public class ChunkFromFileRequestBody extends FileRequestBody { long maxCount = Math.min(mOffset + mChunkSize, mChannel.size()); while (mChannel.position() < maxCount) { - Timber.v("Sink buffer size: %s", sink.buffer().size()); - readCount = mChannel.read(mBuffer); - Timber.v("Read " + readCount + " bytes from file channel to " + mBuffer.toString()); - - sink.buffer().write(mBuffer.array(), 0, readCount); + sink.getBuffer().write(mBuffer.array(), 0, readCount); sink.flush(); - Timber.v("Write " + readCount + " bytes to sink buffer with size " + sink.buffer().size()); - mBuffer.clear(); if (mTransferred < maxCount) { // condition to avoid accumulate progress for repeated chunks mTransferred += readCount; From 5e86e9f0e4cb7ae49a97e33a4461aaaad54b1c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 28 Oct 2020 09:04:17 +0100 Subject: [PATCH 13/14] Determine if a body is loggable based on its content-type --- .../lib/common/http/HttpConstants.java | 8 ++++ .../android/lib/common/http/LogBuilder.kt | 18 ++++++++ .../android/lib/common/http/LogInterceptor.kt | 34 ++++++++------ .../owncloud/android/lib/common/http/utf8.kt | 44 ------------------- 4 files changed, 46 insertions(+), 58 deletions(-) delete mode 100644 owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java index 3850cd3f..b86534a3 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/HttpConstants.java @@ -51,6 +51,14 @@ public class HttpConstants { public static final String ACCEPT_ENCODING_IDENTITY = "identity"; public static final String OC_FILE_REMOTE_ID = "OC-FileId"; + /*********************************************************************************************************** + ************************************************ CONTENT TYPES ******************************************** + ***********************************************************************************************************/ + + public static final String CONTENT_TYPE_XML = "application/xml"; + public static final String CONTENT_TYPE_JSON = "application/json"; + public static final String CONTENT_TYPE_WWW_FORM = "application/x-www-form-urlencoded"; + /*********************************************************************************************************** ************************************************ STATUS CODES ********************************************* ***********************************************************************************************************/ diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt index c85f4fd5..c0ca4fb0 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogBuilder.kt @@ -22,6 +22,10 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_JSON +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_WWW_FORM +import com.owncloud.android.lib.common.http.HttpConstants.CONTENT_TYPE_XML +import okhttp3.MediaType import timber.log.Timber import java.util.Locale @@ -45,3 +49,17 @@ enum class NetworkNode { override fun toString(): String = super.toString().toLowerCase(Locale.ROOT) } + +/** + * Check whether a media type is loggable. + * + * @return true if its type is text, xml, json, or x-www-form-urlencoded. + */ +fun MediaType?.isLoggable(): Boolean = + this?.let { mediaType -> + val mediaTypeString = mediaType.toString() + (mediaType.type == "text" || + mediaTypeString.contains(CONTENT_TYPE_XML) || + mediaTypeString.contains(CONTENT_TYPE_JSON) || + mediaTypeString.contains(CONTENT_TYPE_WWW_FORM)) + } ?: false diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index 30860f54..a6f5dd74 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -99,7 +99,7 @@ class LogInterceptor : Interceptor { logHttp(REQUEST, BODY, requestId, "Type: ${requestBody.contentType()}") logHttp(REQUEST, BODY, requestId, "--> Body start for request") - if (buffer.isProbablyUtf8()) { + if (contentType.isLoggable()) { if (requestBody.contentLength() < LIMIT_BODY_LOG) { logHttp(REQUEST, BODY, requestId, buffer.readString(charset)) } else { @@ -137,7 +137,25 @@ class LogInterceptor : Interceptor { source.request(LIMIT_BODY_LOG) val buffer = source.buffer - if (!buffer.isProbablyUtf8()) { + if (contentType.isLoggable()) { + + if (responseBody.contentLength() < LIMIT_BODY_LOG) { + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) + } else { + logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) + } + logHttp( + RESPONSE, + BODY, + requestId, + "<-- Body end for response -- Omitted: ${ + max( + 0, + responseBody.contentLength() - LIMIT_BODY_LOG + ) + } bytes" + ) + } else { logHttp( RESPONSE, BODY, @@ -145,18 +163,6 @@ class LogInterceptor : Interceptor { "<-- Body end for response -- Binary -- Omitted: ${responseBody.contentLength()} bytes" ) } - - if (responseBody.contentLength() < LIMIT_BODY_LOG) { - logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(charset)) - } else { - logHttp(RESPONSE, BODY, requestId, buffer.clone().readString(LIMIT_BODY_LOG, charset)) - } - logHttp( - RESPONSE, - BODY, - requestId, - "<-- Body end for response -- Omitted: ${max(0, responseBody.contentLength() - LIMIT_BODY_LOG)} bytes" - ) } ?: logHttp(RESPONSE, BODY, requestId, "Empty body") } diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt deleted file mode 100644 index 9591e425..00000000 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/utf8.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2015 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.owncloud.android.lib.common.http - -import java.io.EOFException -import okio.Buffer - -/** - * Returns true if the body in question probably contains human readable text. Uses a small - * sample of code points to detect unicode control characters commonly used in binary file - * signatures. - */ -internal fun Buffer.isProbablyUtf8(): Boolean { - try { - val prefix = Buffer() - val byteCount = size.coerceAtMost(64) - copyTo(prefix, 0, byteCount) - for (i in 0 until 16) { - if (prefix.exhausted()) { - break - } - val codePoint = prefix.readUtf8CodePoint() - if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { - return false - } - } - return true - } catch (_: EOFException) { - return false // Truncated UTF-8 sequence. - } -} From 2b64b83b8939c01fd5aa3e9b34626b1a87d4c8f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Garci=CC=81a=20de=20Prada?= Date: Wed, 28 Oct 2020 09:17:27 +0100 Subject: [PATCH 14/14] Do not log Authorization header --- .../owncloud/android/lib/common/http/LogInterceptor.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt index a6f5dd74..0ca90a47 100644 --- a/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt +++ b/owncloudComLibrary/src/main/java/com/owncloud/android/lib/common/http/LogInterceptor.kt @@ -23,6 +23,7 @@ */ package com.owncloud.android.lib.common.http +import com.owncloud.android.lib.common.http.HttpConstants.AUTHORIZATION_HEADER import com.owncloud.android.lib.common.http.HttpConstants.OC_X_REQUEST_ID import com.owncloud.android.lib.common.http.LogBuilder.logHttp import com.owncloud.android.lib.common.http.NetworkNode.BODY @@ -72,7 +73,12 @@ class LogInterceptor : Interceptor { private fun logHeaders(requestId: String?, headers: Headers, networkPetition: NetworkPetition) { headers.forEach { header -> - logHttp(networkPetition, HEADER, requestId, "${header.first}: ${header.second}") + val headerValue: String = if (header.first.equals(AUTHORIZATION_HEADER, true)) { + "[redacted]" + } else { + header.second + } + logHttp(networkPetition, HEADER, requestId, "${header.first}: $headerValue") } }