Play Framework:如何修改响应体而不阻塞?

时间:2016-08-15 00:00:38

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

我正在使用书籍Reactive Web Applications: Covers Play, Akka, and Reactive Streams切断我的牙齿。第4章,除其他外,教授如何编写过滤器,但本书中显示的代码无法编译,因为在Play 2.4.x中,Enumerator[Array[Byte]]曾经是play.api.http.HttpEntity而在2.5中。 x是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)

在书中:

<!DOCTYPE html>
    <html>
      <head>
        <title>Autofresh</title>
        <link rel="stylesheet" type="text/css" href="styles/styles.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script type="text/javascript" >
        window.onload;
        function detectmob() {
         if( navigator.userAgent.match(/Android/i)
         || navigator.userAgent.match(/webOS/i)
         || navigator.userAgent.match(/iPhone/i)
         || navigator.userAgent.match(/iPad/i)
         || navigator.userAgent.match(/iPod/i)
         || navigator.userAgent.match(/BlackBerry/i)
         || navigator.userAgent.match(/Windows Phone/i)
         ){
            return true;
          }
         else {
            return false;
          }
        }
        if(detectmob()){
          window.alert('success');
          $("#content").width("100%");
        } else {
          window.alert('fail');
        }
        </script>
      </head>
      <body>
        <div id="content" class="mcontent">
          <div id="header">
            //image goes here
            <div id="navbar">

            </div>
          </div>
          <div id="video"></div>
          <div id="registration">

          </div>
        </div>
      </body>
    </html>

正如您所看到的,我的过滤器版本可以正常工作,但它阻碍了未来。我想知道是否有更好的方法可以不阻塞地执行此操作?

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

1 个答案:

答案 0 :(得分:2)

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

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

(请注意map更改为flatMap