Play Framework:如何在不阻塞的情况下修改响应体?
Play Framework: How to modify the response body without blocking?
我正在使用这本书 Reactive Web Applications: Covers Play, Akka, and Reactive Streams 在 Play 上磨牙。第 4 章教如何编写过滤器,但书中显示的代码无法编译,因为在 Play 2.4.x 中,Result.body
曾经是 Enumerator[Array[Byte]]
在 2.5.x 中是 play.api.http.HttpEntity
.
我的滤镜版本如下:
class ScoreFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
override def apply(nextFilter: (RequestHeader) => Future[Result])(rh: RequestHeader) =
nextFilter(rh).map { result =>
if (result.header.status == OK || result.header.status == NOT_ACCEPTABLE) {
val correct = result.session(rh).get("correct").getOrElse(0)
val wrong = result.session(rh).get("wrong").getOrElse(0)
val score = s"\nYour current score is: $correct correct " +
s"answers and $wrong wrong answers"
val contentType = result.body.contentType
val scoreByteString = ByteString(score.getBytes(UTF_8))
val maybeNewBody = result.body.consumeData.map(_.concat(scoreByteString))
import scala.concurrent.duration._
val newBody = Await.result(maybeNewBody, 10 seconds)
result.copy(body = Strict(newBody, contentType))
} else {
result
}
}
}
书中:
// result.body returns a play.api.http.HttpEntity which doesn't have an andThen method
val newBody = result.body andThen Enumerator(score.getBytes(UTF_8))
result.copy(body = newBody)
如您所见,我的过滤器版本有效,但它会阻止未来。我想知道是否有更好的方法来做到这一点而不阻塞?
P.S.: 在将我的问题视为重复问题之前,请注意我已经阅读了以下所有线程,它们将响应正文转换为字符串,这不是我想要的。
Play framework filter that modifies json request and response
如果你想避免Await.result
,你可以这样做:
nextFilter(rh).flatMap { result =>
...
maybeNewBody map { newBody =>
result.copy(body = Strict(newBody, contentType))
}
} else Future.successful(result)
(注意 map
改为 flatMap
)
我正在使用这本书 Reactive Web Applications: Covers Play, Akka, and Reactive Streams 在 Play 上磨牙。第 4 章教如何编写过滤器,但书中显示的代码无法编译,因为在 Play 2.4.x 中,Result.body
曾经是 Enumerator[Array[Byte]]
在 2.5.x 中是 play.api.http.HttpEntity
.
我的滤镜版本如下:
class ScoreFilter @Inject()(implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
override def apply(nextFilter: (RequestHeader) => Future[Result])(rh: RequestHeader) =
nextFilter(rh).map { result =>
if (result.header.status == OK || result.header.status == NOT_ACCEPTABLE) {
val correct = result.session(rh).get("correct").getOrElse(0)
val wrong = result.session(rh).get("wrong").getOrElse(0)
val score = s"\nYour current score is: $correct correct " +
s"answers and $wrong wrong answers"
val contentType = result.body.contentType
val scoreByteString = ByteString(score.getBytes(UTF_8))
val maybeNewBody = result.body.consumeData.map(_.concat(scoreByteString))
import scala.concurrent.duration._
val newBody = Await.result(maybeNewBody, 10 seconds)
result.copy(body = Strict(newBody, contentType))
} else {
result
}
}
}
书中:
// result.body returns a play.api.http.HttpEntity which doesn't have an andThen method
val newBody = result.body andThen Enumerator(score.getBytes(UTF_8))
result.copy(body = newBody)
如您所见,我的过滤器版本有效,但它会阻止未来。我想知道是否有更好的方法来做到这一点而不阻塞?
P.S.: 在将我的问题视为重复问题之前,请注意我已经阅读了以下所有线程,它们将响应正文转换为字符串,这不是我想要的。
Play framework filter that modifies json request and response
如果你想避免Await.result
,你可以这样做:
nextFilter(rh).flatMap { result =>
...
maybeNewBody map { newBody =>
result.copy(body = Strict(newBody, contentType))
}
} else Future.successful(result)
(注意 map
改为 flatMap
)