diff --git a/CHANGELOG.md b/CHANGELOG.md index cccf7a05d..47ffeebbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Please add your entries according to this format. ### Fixed * Fixed not setting request body type correctly [#538]. +* Fixed request headers not being redacted in case of failures [#545]. ### Removed diff --git a/library/src/main/java/com/chuckerteam/chucker/api/ChuckerInterceptor.kt b/library/src/main/java/com/chuckerteam/chucker/api/ChuckerInterceptor.kt index bb5b7f19b..f58eb8e63 100755 --- a/library/src/main/java/com/chuckerteam/chucker/api/ChuckerInterceptor.kt +++ b/library/src/main/java/com/chuckerteam/chucker/api/ChuckerInterceptor.kt @@ -14,8 +14,8 @@ import com.chuckerteam.chucker.internal.support.contentType import com.chuckerteam.chucker.internal.support.hasBody import com.chuckerteam.chucker.internal.support.hasSupportedContentEncoding import com.chuckerteam.chucker.internal.support.isProbablyPlainText +import com.chuckerteam.chucker.internal.support.redact import com.chuckerteam.chucker.internal.support.uncompress -import okhttp3.Headers import okhttp3.Interceptor import okhttp3.Response import okhttp3.ResponseBody.Companion.asResponseBody @@ -52,7 +52,7 @@ public class ChuckerInterceptor private constructor( private val cacheDirectoryProvider = builder.cacheDirectoryProvider ?: CacheDirectoryProvider { context.filesDir } private val alwaysReadResponseBody = builder.alwaysReadResponseBody private val headersToRedact = builder.headersToRedact.toMutableSet() - private val requestProcessor = RequestProcessor(context, collector, maxContentLength) + private val requestProcessor = RequestProcessor(context, collector, maxContentLength, headersToRedact) /** Adds [headerName] into [headersToRedact] */ public fun redactHeader(vararg headerName: String) { @@ -87,8 +87,8 @@ public class ChuckerInterceptor private constructor( transaction.apply { // includes headers added later in the chain - setRequestHeaders(filterHeaders(response.request.headers)) - setResponseHeaders(filterHeaders(response.headers)) + setRequestHeaders(response.request.headers.redact(headersToRedact)) + setResponseHeaders(response.headers.redact(headersToRedact)) isResponseBodyPlainText = responseEncodingIsSupported requestDate = response.sentRequestAtMillis @@ -176,17 +176,6 @@ public class ChuckerInterceptor private constructor( } } - /** Overrides all headers from [headersToRedact] with `**` */ - private fun filterHeaders(headers: Headers): Headers { - val builder = headers.newBuilder() - for (name in headers.names()) { - if (headersToRedact.any { userHeader -> userHeader.equals(name, ignoreCase = true) }) { - builder.set(name, "**") - } - } - return builder.build() - } - private inner class ChuckerTransactionReportingSinkCallback( private val response: Response, private val transaction: HttpTransaction diff --git a/library/src/main/java/com/chuckerteam/chucker/internal/support/OkHttpUtils.kt b/library/src/main/java/com/chuckerteam/chucker/internal/support/OkHttpUtils.kt index 023bcbceb..8fc5c9c1f 100644 --- a/library/src/main/java/com/chuckerteam/chucker/internal/support/OkHttpUtils.kt +++ b/library/src/main/java/com/chuckerteam/chucker/internal/support/OkHttpUtils.kt @@ -64,3 +64,13 @@ internal fun Source.uncompress(headers: Headers) = if (headers.containsGzip) { } else { this } + +internal fun Headers.redact(names: Iterable): Headers { + val builder = newBuilder() + for (name in names()) { + if (names.any { userHeader -> userHeader.equals(name, ignoreCase = true) }) { + builder[name] = "**" + } + } + return builder.build() +} diff --git a/library/src/main/java/com/chuckerteam/chucker/internal/support/RequestProcessor.kt b/library/src/main/java/com/chuckerteam/chucker/internal/support/RequestProcessor.kt index e5904d473..bd0162e7e 100644 --- a/library/src/main/java/com/chuckerteam/chucker/internal/support/RequestProcessor.kt +++ b/library/src/main/java/com/chuckerteam/chucker/internal/support/RequestProcessor.kt @@ -13,6 +13,7 @@ internal class RequestProcessor( private val context: Context, private val collector: ChuckerCollector, private val maxContentLength: Long, + private val headersToRedact: Set, ) { fun process(request: Request, transaction: HttpTransaction): Request { processMetadata(request, transaction) @@ -23,7 +24,7 @@ internal class RequestProcessor( private fun processMetadata(request: Request, transaction: HttpTransaction) { transaction.apply { - setRequestHeaders(request.headers) + setRequestHeaders(request.headers.redact(headersToRedact)) populateUrl(request.url) requestDate = System.currentTimeMillis() diff --git a/library/src/test/java/com/chuckerteam/chucker/api/ChuckerInterceptorTest.kt b/library/src/test/java/com/chuckerteam/chucker/api/ChuckerInterceptorTest.kt index 1176301df..975048695 100644 --- a/library/src/test/java/com/chuckerteam/chucker/api/ChuckerInterceptorTest.kt +++ b/library/src/test/java/com/chuckerteam/chucker/api/ChuckerInterceptorTest.kt @@ -17,6 +17,7 @@ import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.SocketPolicy import okio.Buffer import okio.ByteString import okio.ByteString.Companion.encodeUtf8 @@ -496,5 +497,30 @@ internal class ChuckerInterceptorTest { assertThat(transaction.requestPayloadSize).isEqualTo(request.body!!.contentLength()) } + @ParameterizedTest + @EnumSource(value = ClientFactory::class) + fun requestHeaders_areRedacted_whenServerFails(factory: ClientFactory) { + val chuckerInterceptor = ChuckerInterceptorDelegate( + maxContentLength = SEGMENT_SIZE, + headersToRedact = setOf("Header-To-Redact"), + cacheDirectoryProvider = { tempDir }, + ) + val client = factory.create(chuckerInterceptor) + + val request = Request.Builder().url(serverUrl).header("Header-To-Redact", "Hello").build() + server.enqueue(MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_START)) + runCatching { client.newCall(request).execute() } + + val transaction = chuckerInterceptor.expectTransaction() + assertThat(transaction.requestHeaders).contains( + """ + | { + | "name": "Header-To-Redact", + | "value": "**" + | } + """.trimMargin() + ) + } + private fun RequestBody.toServerRequest() = Request.Builder().url(serverUrl).post(this).build() }