根据play documentation,这是自定义操作的外观:
object CustomAction extends ActionBuilder[Request] {
def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = {
block(request)
}
}
但是说,如果我想在每个响应正文后附加“foo”,我该怎么做?显然下面是行不通的:
block.andThen(result => result.map(r => r.body.toString + "foo")).apply(request)
有任何想法吗?
更新:值得一提的是,此操作将主要用作 Controller 中的异步操作:
def test = CustomAction.async {
//...
}
最佳答案
您需要从Enumerator[Array[Byte]]
主体中获取Result
并将其提供给iteratee以实际使用结果主体,然后才能对其进行修改。因此,使用一个简单的iteratee消耗结果主体并将其转换为String可能类似于:
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")
}
}
我使用
flatMap
是因为运行Iteratee.flatten
是Future[T]
。请查看https://www.playframework.com/documentation/2.4.x/Enumerators,以获取有关如何使用枚举器/迭代器的更多详细信息。