基本过滤器Play Framework 2中的访问请求主体

时间:2015-03-14 09:44:23

标签: scala playframework-2.3

我是Scala的新手。 如在https://www.playframework.com/documentation/2.3.x/ScalaHttpFilters中的播放框架官方文档中所述:

  

Play提供了一个名为EssentialFilter的低级过滤器API   让您完全访问请求的正文。

但是没有任何方法可以访问requestHeader对象中的请求正文。

import play.api.Logger
import play.api.mvc._
import play.api.libs.concurrent.Execution.Implicits.defaultContext

object LoggingFilter extends EssentialFilter {
  def apply(nextFilter: EssentialAction) = new EssentialAction {
    def apply(requestHeader: RequestHeader) = {
      val startTime = System.currentTimeMillis
      nextFilter(requestHeader).map { result =>
        val endTime = System.currentTimeMillis
        val requestTime = endTime - startTime
        Logger.info(s"${requestHeader.method} ${requestHeader.uri}" +
          s" took ${requestTime}ms and returned ${result.header.status}")
        result.withHeaders("Request-Time" -> requestTime.toString)
      }
    }
  }
}

2 个答案:

答案 0 :(得分:5)

您在创建EssentialFilter.apply时实施的抽象方法EssentialFilter会返回EssentialAction,其基本上是从RequestHeaderIteratee[Array[Byte], Result]的函数哪个播放将提供http正文的传入字节块。

如果您不熟悉iteratee API,则上面的签名基本上意味着,接受Array[Byte]类型的数据块并且迟早会产生Result那些。

正常游戏ActionEssentialAction的子类,使用BodyParser解析身体,然后提供其结果(Request将请求标头和已解析的主体都放入一个函数中,该函数又返回Future[Result]

因此,如果您只有一个过滤器,那么过滤器中的next: EssentialAction基本上就是实际的控制器操作。你可以使用它的Iteratee[Array[Bytes], Result]并用它包装,这样就可以在身体解析器触摸它之前访问请求的主体。

因此,要实现您想要的目标,您需要了解Iteratees如何工作以及如何使用Enumeratees转换或查看输入到迭代中的数据。

一些起点

播放框架文档有一些关于迭代的非常好的信息:https://www.playframework.com/documentation/2.3.x/Iteratees

James Roper(播放技术主管)也有一篇很好的博客文章可能会有所帮助: https://jazzy.id.au/2012/11/06/iteratees_for_imperative_programmers.html

重要提示

过滤器如何在游戏中工作,因此无法使用过滤器查看已解析的主体。除非你创建一个将解析主体的枚举,但仍然将字节传递给实际的动作(这将使你解析主体两次)。

如果这是您想要的,那么您最好使用ActionBuilder并创建自己的自定义Action,以便查看已解析的请求。

答案 1 :(得分:0)

你不想在过滤级别解析请求体,因为在过滤过程中没有解析主体,你必须缓冲,解析和流,所以最好使用动作组合

    object LoggingAction extends ActionBuilder[Request] {
      def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
          Logger.debug(request.body.asInstanceOf[AnyContentAsJson].json.toString())    
          block(request)
  }
}

在控制器端使用,如

 def index = LoggingAction {...