Play Framework 2.6 WSClient REQUEST Logging

2,113 views
Skip to first unread message

Tony Culshaw

unread,
Jul 16, 2017, 8:16:58 PM7/16/17
to Play Framework
I have a mandatory requirement for auditing reasons to log REQUESTS as well as responses in the WSClient.

In 2.5.x after a bit of headscratching, I had the following....

import javax.inject._
import akka.actor._
import java.nio.charset.StandardCharsets
import scala.concurrent.Future
import org.asynchttpclient.util.HttpUtils
import play.api.libs.ws._

import scala.concurrent.Future
import play.api.libs.ws.ahc._

@Singleton
class MyWSRequestLogger @Inject() (implicit val system: ActorSystem, ..... ) extends WSRequestFilter {
  ....
  def apply(executor: WSRequestExecutor): WSRequestExecutor = {
    new WSRequestExecutor {
      override def execute(request: WSRequest): Future[WSResponse] = {
        val ahcRequest = request.asInstanceOf[AhcWSRequest]
        executor.execute(request) map { response =>
           ....
           toBody(ahcRequest) map { stringRequestBody =>
              // log request body in various formats (json/xml/form posts) as well as everything else
              .....
           }
        }
      }
    }

    protected def findCharset(request: AhcWSRequest): String = {
    request.contentType.map { ct =>
      Option(HttpUtils.parseCharset(ct)).getOrElse {
        StandardCharsets.UTF_8
      }.name()
    }.getOrElse(HttpUtils.parseCharset("UTF-8").name())
  }

  def toBody(request: AhcWSRequest): Option[String] = {
    // body (note that this has only been checked for text, not binary)
    request.getBody.map { body =>
      val charset = findCharset(request)
      body.decodeString(charset)
    }

  }
}  

I then add this wsLogger: WSRequestFilter to each wsclient call as per

ws.url( someUrl )
    .withHeaders( .... )
    .withRequestFilter(wsLogger).withQueryString( .... ).get......

Works great in play 2.5:)

I read through the Migration Guides doco and had a go upgrading to 2.6.x and this (wsclient request logging)was a real showstopper. With the shadow stuff I'm not at all clear how I can get the Request body into a string. Totally stumped!

Has anyone managed to do this yet?

Will Sargent

unread,
Jul 18, 2017, 5:30:03 PM7/18/17
to Play Framework
So this should be logging the same way, using 

ws.url(s"http://localhost:$testServerPort")
  .withRequestFilter(AhcCurlRequestLogger())
  .put(Map("key" -> Seq("value")))


You can look at the curl logger source code in 2.6 as an example:

Reply all
Reply to author
Forward
0 new messages