Scala Play 2.5.0 2.5.1 Фильтрация с доступом к телу результата

Я не нашел способа получить тело в фильтре в Play 2.5.x. Я хочу создать «BadRequestLogFilter», который должен регистрировать запрос и результат, если мое приложение возвращает код состояния 400-500.

В Play 2.4.x я использовал Iteratees, и это сработало. Мне не удалось перенести этот фрагмент кода в Play 2.5.x. Может ли кто-нибудь дать мне подсказку здесь? Может быть, подход с отверстием, чтобы поместить тело в фильтр, - плохая идея?

Вот мой старый (в 2.4.х работает нормально) фильтр для Play 2.4.х

class BadRequestLogFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {
  val logger = Logger("bad_status").underlyingLogger

  override def apply(next: (RequestHeader) => Future[Result])(request: RequestHeader): Future[Result] = {
    val resultFuture = next(request)
    resultFuture.foreach(result => {

      val status = result.header.status
      if (status < 200 || status >= 400) {
        val c = Try(request.tags(Router.Tags.RouteController))
        val a = Try(request.tags(Router.Tags.RouteActionMethod))

        val body = result.body.run(Iteratee.fold(Array.empty[Byte]) { (memo, nextChunk) => memo ++ nextChunk })
        val futResponse = body.map(bytes => new String(bytes))
        futResponse.map { response =>

          val m = Map("method" -> request.method,
            "uri" -> request.uri,
            "status" -> status,
            "response" -> response,
            "request" -> request,
            "controller" -> c.getOrElse("empty"),
            "actionMethod" -> a.getOrElse("empty"))

          val msg = m.map { case (k, v) => s"$k=$v" }.mkString(", ")
          logger.info(appendEntries(m), msg)
        }
      }
    })
    resultFuture
  }
}

Думаю, мне просто нужна действительная замена этой строки здесь:

val body = result.body.run(Iteratee.fold(Array.empty[Byte]) { (memo, nextChunk) => memo ++ nextChunk })

person gun    schedule 11.04.2016    source источник


Ответы (1)


Тело результата в Play 2.5.x имеет тип HttpEntity

Итак, когда у вас есть результат, вы можете получить тело, а затем материализовать его:

val body = result.body.consumeData(mat)

Здесь mat — это implicit Materializer, которое у вас есть. Это вернет вам Future[ByteString], который вы затем можете декодировать, чтобы получить строковое представление (для простоты я опустил здесь будущую обработку):

val bodyAsString = body.decodeString("UTF-8")
logger.info(bodyAsString)
person Anton    schedule 11.04.2016