7

Play フレームワークで応答本文を出力する方法を探しています。次のようなコードがあります。

object AccessLoggingAction extends ActionBuilder[Request] {
  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    Logger.info(s"""Request:
      id=${request.id} 
      method=${request.method} 
      uri=${request.uri} 
      remote-address=${request.remoteAddress} 
      body=${request.body}
    """)
    val ret = block(request)
    /*
    ret.map {result =>
      Logger.info(s"""Response:
      id=${request.id} 
      body=${result.body}
      """)
    }
    */ //TODO: find out how to print result.body (be careful not to consume the enumerator)
    ret
  }
}

現在、コメントアウトされたコードは私が望むように機能していません。つまり、次のように出力されます。

Response:
id=1
body=play.api.libs.iteratee.Enumerator$$anon$18@39e6c1a2

そのため、Enumerator[Array[Byte]] から文字列を取得する方法を見つける必要があります。これを読んで列挙子の概念を把握しようとしました: http://mandubian.com/2012/08/27/understanding-play2-iteratees-for-normal-humans/

だから...、私がそれを正しく理解していれば:

  1. 列挙子を文字列に変換する過程で、列挙子を枯渇させるべきではありません。そうしないと、クライアントは何も受け取りません。

  2. T / フィルターメカニズムを実装する方法を理解したとしましょう。しかし、それでは...非ブロッキングストリーミングフレームワークとしてのPlayフレームワークの目的を無効にしないでしょうか(toStringを呼び出す前に、メモリ内にバイトの完全な配列を構築し、最終的にログに記録するため)?

では、応答をログに記録する正しい方法は何ですか?

前もってありがとう、ラカ

4

3 に答える 3

2

私のように、内部でログを記録し( https://stackoverflow.com/a/27630208/1781549result.body &> Enumeratee.mapで提案されているように)、結果の本文が複数のチャンクで表示される場合、各チャンクは個別にログに記録されます。あなたはおそらくこれを望んでいません。

私は次のように実装します:

val ret = block(request).flatMap { result =>
  val consume = Iteratee.consume[Array[Byte]]()
  val bodyF = Iteratee.flatten(result.body(consume)).run
  bodyF.map { bodyBytes: Array[Byte] =>
    //
    // Log the body
    //

    result.copy(body = Enumerator(bodyBytes))
  }
}

ただし、注意してください。これの全体的な考え方は、result.bodyログを記録する前に Enumerator からのすべてのデータを消費することです (そして、新しい Enumerator を返します)。したがって、レスポンスが大きい場合、またはストリーミングに依存している場合は、おそらく望ましくないことでもあります。

于 2016-04-27T10:51:29.670 に答える