Skip to content

Commit

Permalink
Configurable sensitive headers when logging
Browse files Browse the repository at this point in the history
  • Loading branch information
adamw committed Sep 10, 2020
1 parent bc5e8d4 commit 782590e
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 46 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ val scalaTest = "org.scalatest" %% "scalatest" % scalaTestVersion
val zioVersion = "1.0.1"
val zioInteropRsVersion = "1.0.3.5"

val sttpModelVersion = "1.2.0-RC2"
val sttpModelVersion = "1.2.0-RC3"
val sttpSharedVersion = "1.0.0-RC5"

val logback = "ch.qos.logback" % "logback-classic" % "1.2.3"
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/sttp/client/RequestMetadata.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait RequestMetadata extends HasHeaders {
def method: Method
def uri: Uri

override def toString: String = s"RequestMetadata($method,$uri,${headers.map(_.toStringSafe)})"
override def toString: String = s"RequestMetadata($method,$uri,${headers.map(_.toStringSafe())})"
}

object RequestMetadata {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/sttp/client/RequestT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,8 @@ case class RequestT[U[_], T, -R](
case _ => "(no method & uri set)"
}

def show(includeBody: Boolean = true): String = {
val headers = this.headers.map(_.toStringSafe).mkString(", ")
def show(includeBody: Boolean = true, sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders): String = {
val headers = this.headers.map(_.toStringSafe(sensitiveHeaders)).mkString(", ")
val body = if (includeBody) s", body: ${this.body.show}" else ""
val methodAndUri = (this.method, this.uri) match {
case (m: Method, u: Uri) =>
Expand Down
8 changes: 4 additions & 4 deletions core/src/main/scala/sttp/client/Response.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package sttp.client

import sttp.model.{Header, StatusCode}
import sttp.model.{Header, HeaderNames, StatusCode}

import scala.collection.immutable.Seq

Expand All @@ -17,13 +17,13 @@ case class Response[T](
history: List[Response[Unit]],
request: RequestMetadata
) extends ResponseMetadata {
def show(includeBody: Boolean = true): String = {
val headers = headersToStringSafe.mkString(", ")
def show(includeBody: Boolean = true, sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders): String = {
val headers = headersToStringSafe(sensitiveHeaders).mkString(", ")
val body = if (includeBody) s", body: ${this.body}" else ""
s"$code $statusText, headers: $headers$body"
}

override def toString: String = s"Response($body,$code,$statusText,$headersToStringSafe,$history,$request)"
override def toString: String = s"Response($body,$code,$statusText,${headersToStringSafe()},$history,$request)"
}

object Response {
Expand Down
5 changes: 3 additions & 2 deletions core/src/main/scala/sttp/client/ResponseMetadata.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ trait ResponseMetadata extends HasHeaders {
def isClientError: Boolean = code.isClientError
def isServerError: Boolean = code.isServerError

override def toString: String = s"ResponseMetadata($code,$statusText,$headersToStringSafe)"
override def toString: String = s"ResponseMetadata($code,$statusText,${headersToStringSafe()})"

protected def headersToStringSafe: Seq[String] = headers.map(_.toStringSafe)
protected def headersToStringSafe(sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders): Seq[String] =
headers.map(_.toStringSafe(sensitiveHeaders))
}

object ResponseMetadata {
Expand Down
15 changes: 11 additions & 4 deletions core/src/main/scala/sttp/client/logging/Log.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sttp.client.logging

import sttp.client.{Request, Response}
import sttp.model.HeaderNames

import scala.concurrent.duration.Duration

Expand All @@ -25,12 +26,17 @@ trait Log[F[_]] {
/**
* Default implementation of [[Log]] to be used by the [[LoggingBackend]].
*/
class DefaultLog[F[_]](logger: Logger[F], beforeCurlInsteadOfShow: Boolean = false, logRequestBody: Boolean = false)
extends Log[F] {
class DefaultLog[F[_]](
logger: Logger[F],
beforeCurlInsteadOfShow: Boolean = false,
logRequestBody: Boolean = false,
sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders
) extends Log[F] {

def beforeRequestSend(request: Request[_, _]): F[Unit] =
logger.debug(
s"Sending request: ${if (beforeCurlInsteadOfShow) request.toCurl else request.show(includeBody = false)}"
s"Sending request: ${if (beforeCurlInsteadOfShow) request.toCurl
else request.show(includeBody = logRequestBody, sensitiveHeaders)}"
)

override def response(
Expand All @@ -40,7 +46,8 @@ class DefaultLog[F[_]](logger: Logger[F], beforeCurlInsteadOfShow: Boolean = fal
elapsed: Option[Duration]
): F[Unit] =
logger.debug {
val responseAsString = response.copy(body = responseBody.getOrElse("")).show(responseBody.isDefined)
val responseAsString =
response.copy(body = responseBody.getOrElse("")).show(responseBody.isDefined, sensitiveHeaders)
s"Request: ${request.showBasic}${took(elapsed)}, response: $responseAsString"
}

Expand Down
6 changes: 4 additions & 2 deletions core/src/main/scala/sttp/client/logging/LoggingBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit
import sttp.capabilities.Effect
import sttp.client._
import sttp.client.listener.{ListenerBackend, RequestListener}
import sttp.model.HeaderNames
import sttp.monad.MonadError
import sttp.monad.syntax._

Expand All @@ -17,9 +18,10 @@ object LoggingBackend {
includeTiming: Boolean = true,
beforeCurlInsteadOfShow: Boolean = false,
logRequestBody: Boolean = false,
logResponseBody: Boolean = false
logResponseBody: Boolean = false,
sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders
): SttpBackend[F, S] = {
val log = new DefaultLog(logger, beforeCurlInsteadOfShow, logRequestBody)
val log = new DefaultLog(logger, beforeCurlInsteadOfShow, logRequestBody, sensitiveHeaders)
apply(delegate, log, includeTiming, logResponseBody)
}

Expand Down
12 changes: 10 additions & 2 deletions docs/backends/wrappers/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The `sttp.client.logging.LoggingBackend` can log requests and responses which end successfully or with an exception. It can be created given:

* a `sttp.client.logging.Logger`, which is an integration point with logging libraries. One such integration that is available with sttp-client is slf4j (see below), but custom ones can be easily added.
* a `sttp.client.logging.Logger`, which is an integration point with logging libraries. Two such integration that are available with sttp-client is slf4j and scribe (see below), but custom ones can be easily added.
* a `sttp.client.logging.Log`, which constructs messages and performs logging actions. A custom implementation can be provided to change default log levels or log message content.

By default, the following options are exposed:
Expand All @@ -20,7 +20,7 @@ The messages are by default logged on these levels:

## Using slf4j

To use the slf4j logging backend wrapper, add the following dependency to your project:
To use the [slf4j](http://www.slf4j.org) logging backend wrapper, add the following dependency to your project:

```
"com.softwaremill.sttp.client" %% "slf4j-backend" % "@VERSION@"
Expand All @@ -42,3 +42,11 @@ basicRequest.get(uri"https://httpbin.org/get").send(backend)
```

To create a customised logging backend, see the section on [custom backends](custom.md).

## Using scribe

To use the [scribe](https://github.com/outr/scribe) logging backend wrapper, add the following dependency to your project:

```
"com.softwaremill.sttp.client" %% "scribe-backend" % "@VERSION@"
```

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@ package sttp.client.logging.scribe

import sttp.client._
import sttp.client.logging.LoggingBackend
import sttp.model.HeaderNames

object ScribeLoggingBackend {
def apply[F[_], S](
delegate: SttpBackend[F, S],
includeTiming: Boolean = true,
beforeCurlInsteadOfShow: Boolean = false,
logRequestBody: Boolean = false,
logResponseBody: Boolean = false
logResponseBody: Boolean = false,
sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders
): SttpBackend[F, S] =
LoggingBackend(
delegate,
logger = ScribeLogger(delegate.responseMonad),
includeTiming,
beforeCurlInsteadOfShow,
logRequestBody,
logResponseBody
logResponseBody,
sensitiveHeaders
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ package sttp.client.logging.slf4j

import sttp.client._
import sttp.client.logging.LoggingBackend
import sttp.model.HeaderNames

object Slf4jLoggingBackend {
def apply[F[_], S](
delegate: SttpBackend[F, S],
includeTiming: Boolean = true,
beforeCurlInsteadOfShow: Boolean = false,
logRequestBody: Boolean = false,
logResponseBody: Boolean = false
logResponseBody: Boolean = false,
sensitiveHeaders: Set[String] = HeaderNames.SensitiveHeaders
): SttpBackend[F, S] = {
val logger = new Slf4jLogger("sttp.client.logging.slf4j.Slf4jLoggingBackend", delegate.responseMonad)
LoggingBackend(delegate, logger, includeTiming, beforeCurlInsteadOfShow, logRequestBody, logResponseBody)
LoggingBackend(
delegate,
logger,
includeTiming,
beforeCurlInsteadOfShow,
logRequestBody,
logResponseBody,
sensitiveHeaders
)
}
}

0 comments on commit 782590e

Please sign in to comment.