Nonos
Nonos

Reputation: 2518

Scala play http filters: how to find the request body

I'm trying to write a filter similar to the simple one described in http://www.playframework.com/documentation/2.1.1/ScalaHttpFilters but I need to access the request body. The documentation below states that "when we invoke next, we get back an Iteratee. You could wrap this in an Enumeratee to do some transformations if you wished." I'm trying to figure out how to wrap the Iteratee so I can get the request body as a string within the filter so I can log that as well.

Upvotes: 10

Views: 4676

Answers (3)

Setheron
Setheron

Reputation: 3740

I spent some time on this. I am no means a Scala expert but this works pretty well! :)

object AccessLog extends EssentialFilter {
  def apply(nextFilter: EssentialAction) = new EssentialAction {
    def apply(requestHeader: RequestHeader) = {
      val startTime = System.currentTimeMillis

      nextFilter(requestHeader).map { result =>
        val endTime = System.currentTimeMillis
        val requestTime = endTime - startTime

        val bytesToString: Enumeratee[ Array[Byte], String ] = Enumeratee.map[Array[Byte]]{ bytes => new String(bytes) } 
        val consume: Iteratee[String,String] = Iteratee.consume[String]()    
        val resultBody : Future[String] = result.body |>>> bytesToString &>> consume

        resultBody.map {
          body =>
            Logger.info(s"${requestHeader.method} ${requestHeader.uri}" +
          s" took ${requestTime}ms and returned ${result.header.status}")
            val jsonBody = Json.parse(body)
            Logger.debug(s"Response\nHeader:\n${result.header.headers.toString}\nBody:\n${Json.prettyPrint(jsonBody)}")
        }

         result.withHeaders("Request-Time" -> requestTime.toString)

      }
    }
  }

The end result will print the body as a Json String (pretty printed).

Upvotes: -1

Julien Tournay
Julien Tournay

Reputation: 544

First thing you have to know is when the Filter is invoked, the request body is not parsed yet. That's why it's giving you a RequestHeader. You'll have to find out the type of body, and call the proper body parser accordingly.

You can find a example of body parsing in the CSRF filter (It can lookup for CSRF tokens in the first bytes of the request body).

See: https://github.com/playframework/playframework/blob/master/framework/src/play-filters-helpers/src/main/scala/csrf.scala#L221-L233.

Hope it helps.

Upvotes: 7

daniel langer
daniel langer

Reputation: 1975

In the controller method that routes to the action, simply call

Map<String, String[]> params = request().queryString();

This will get you a map of parameters, where you can then call

params.get("someParam")[0] 

to get the param (if it is a single value). If the param is a list, ignore the indexing andthat will return an array.

Upvotes: -4

Related Questions