Play 2.4: intercept and modify response body

2019-05-15 01:46发布

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 {
    //...
}

1条回答
啃猪蹄的小仙女
2楼-- · 2019-05-15 02:05

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.

查看更多
登录 后发表回答