Repository: square/okhttp
File: okhttp-logging-interceptor/src/test/java/okhttp3/logging/HttpLoggingInterceptorTest.kt (Kotlin)

Code before:
      .assertLogMatch(Regex("""<-- 200 OK $url \(\d+ms\)"""))
      .assertLogEqual("Content-Length: 0")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("<-- END HTTP")
      .assertNoMoreLogs()
    networkLogs
      .assertLogEqual("--> GET $url http/1.1")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("Host: $host")
      .assertLogEqual("Connection: Keep-Alive")
      .assertLogEqual("Accept-Encoding: gzip")
      .assertLogMatch(Regex("""User-Agent: okhttp/.+"""))
      .assertLogEqual("--> END GET")
      .assertLogMatch(Regex("""<-- 200 OK $url \(\d+ms\)"""))
      .assertLogEqual("Content-Length: 0")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("<-- END HTTP")
      .assertNoMoreLogs()
  }

  @Test
  fun sensitiveQueryParamsAreRedacted() {
    url = server.url("/api/login?user=test_user&authentication=basic&password=confidential_password")
    val sanitizedUrl = "${server.url("/")}api/login?user=██&authentication=basic&password=██"
    val sanitizedUrlPattern = sanitizedUrl.replace("?", """\?""")

    val networkInterceptor =
      HttpLoggingInterceptor(networkLogs).setLevel(
        Level.BASIC,
      )
    networkInterceptor.redactQueryParams("user", "passWord")

    val applicationInterceptor =
      HttpLoggingInterceptor(applicationLogs).setLevel(
        Level.BASIC,
      )
    applicationInterceptor.redactQueryParams("user", "PassworD")

    client =
      OkHttpClient.Builder()
        .addNetworkInterceptor(networkInterceptor)
        .addInterceptor(applicationInterceptor)
        .build()
    server.enqueue(
      MockResponse.Builder()
        .build(),
    )
    val response =

Review comment (security):
Can you add a test for duplicate query params, retaining the order and encoded params.

It might be worth exposing `sanitizeUrl` as internal for testing, and calling directly.

Code after:
      .assertLogMatch(Regex("""<-- 200 OK $url \(\d+ms\)"""))
      .assertLogEqual("Content-Length: 0")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("<-- END HTTP")
      .assertNoMoreLogs()
    networkLogs
      .assertLogEqual("--> GET $url http/1.1")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("Host: $host")
      .assertLogEqual("Connection: Keep-Alive")
      .assertLogEqual("Accept-Encoding: gzip")
      .assertLogMatch(Regex("""User-Agent: okhttp/.+"""))
      .assertLogEqual("--> END GET")
      .assertLogMatch(Regex("""<-- 200 OK $url \(\d+ms\)"""))
      .assertLogEqual("Content-Length: 0")
      .assertLogEqual("SeNsItIvE: ██")
      .assertLogEqual("Not-Sensitive: Value")
      .assertLogEqual("<-- END HTTP")
      .assertNoMoreLogs()
  }

  @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
  @Test
  fun sensitiveQueryParamsAreRedacted() {
    url = server.url("/api/login?user=test_user&authentication=basic&password=confidential_password")
    val networkInterceptor =
      HttpLoggingInterceptor(networkLogs).setLevel(
        Level.BASIC,
      )
    networkInterceptor.redactQueryParams("user", "passWord")

    val applicationInterceptor =
      HttpLoggingInterceptor(applicationLogs).setLevel(
        Level.BASIC,
      )
    applicationInterceptor.redactQueryParams("user", "PassworD")

    client =
      OkHttpClient.Builder()
        .addNetworkInterceptor(networkInterceptor)
        .addInterceptor(applicationInterceptor)
        .build()
    server.enqueue(
      MockResponse.Builder()
        .build(),
    )
    val response =
      client
        .newCall(