Caballero
Caballero

Reputation: 12111

Play 2.4: intercept and modify response body

According to play documentation this is what a custom action should look like:

object CustomAction extends ActionBuilder[Request] {
    def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = {
        block(request)
    }
}

But say if I wanted to append "foo" to every response body, how do I do that? Obviously below doesn't work:

block.andThen(result => result.map(r => r.body.toString + "foo")).apply(request)

Any ideas?

UPDATE: Something worth mentioning is that this action would be mostly used as asynchronous in the controller:

def test = CustomAction.async {
    //...
}

Upvotes: 3

Views: 880

Answers (1)

josephpconley
josephpconley

Reputation: 1723

You'll need to take the Enumerator[Array[Byte]] from the Result body and feed it to an iteratee to actually consume the result body before you can modify it. So a simple iteratee that consumes the result body and converts to a String might look like:

block.apply(request).flatMap { res =>
  Iteratee.flatten(res.body |>> Iteratee.consume[Array[Byte]]()).run.map { byteArray =>
    val bodyStr = new String(byteArray.map(_.toChar))
    Ok(bodyStr + "foo")
  }
}

I used flatMap as the result of running Iteratee.flatten is a Future[T]. Check out https://www.playframework.com/documentation/2.4.x/Enumerators for more details on how to work with Enumerators/Iteratees.

Upvotes: 2

Related Questions