【问题标题】:Play Framework: How to modify the response body without blocking?Play Framework:如何在不阻塞的情况下修改响应体?
【发布时间】:2016-08-15 00:00:38
【问题描述】:

我正在使用这本书 Reactive Web Applications: Covers Play, Akka, and Reactive Streams 在 Play 上磨牙。第 4 章,除其他外,教授如何编写过滤器,但书中显示的代码无法编译,因为在 Play 2.4.x 中,Result.body 曾经是 Enumerator[Array[Byte]],而在 2.5.x 中是 @ 987654327@.

我的过滤器版本如下:

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.:在将我的问题视为重复问题之前,请注意我已经阅读了以下所有主题,它们将响应正文转换为字符串,这不是我想要的。

Scala play http filters: how to find the request body

Play framework filter that modifies json request and response

Play 2.4: intercept and modify response body

【问题讨论】:

    标签: scala playframework akka servlet-filters playframework-2.5


    【解决方案1】:

    如果你想避开Await.result,你可以这样做:

    nextFilter(rh).flatMap { result =>
      ...
      maybeNewBody map { newBody =>
        result.copy(body = Strict(newBody, contentType))
      }
    } else Future.successful(result)
    

    (注意map更改为flatMap

    【讨论】:

    • 可行,但我必须将正文更改为Strict。我很好奇是否可以使用IterateesEnumerators 来避免这种情况?
    • HttpEntity 的唯一选项是 StrictStreamedChunked。根据文档,Strict 是您想要的,因为您在内存中有内容:playframework.com/documentation/2.5.2/api/java/play/http/…
    • 我也是这么想的,但是,我想知道在过滤器中我们是否总是知道身体的类型。正如你所说,有 3 个。我给作者 Manuel Bernhardt 发了电子邮件。如果他提供替代方案,将在此处发布。同时,我会接受你的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多