Get Response body from play.api.mvc.Action[AnyCont

2019-04-05 13:06发布

I have the following Play (Scala) code:

object Experiment extends Controller {

 //routes file directs /genki here
 def genki(name: String) = Action(pipeline(name))

 def pipeline(name: String) = {
   req:play.api.mvc.RequestHeader => {
      val template = views.html.genki(name)
      Experiment.Status(200).apply(template).as("text/html")
   }
 }

 def simple = Action {
   SimpleResult(
      header = ResponseHeader(200, Map(CONTENT_TYPE -> "text/plain")),
      body = Enumerator("Hello World!".getBytes())
   )
 }

}

This compiles fine and works as expected.

Using the scala REPL how can I display the actual html?

I have:

 scala> val action = simple
 action: play.api.mvc.Action[play.api.mvc.AnyContent] = Action(parser=BodyParser(anyContent))    

which I take to mean that now the value reference 'action' in the REPL is an Action object which is type-constrained for AnyContent (is that correct way to say it?).

how can I now use this Action to print out the Http Response html content?

Many thanks

3条回答
做自己的国王
2楼-- · 2019-04-05 13:14

Rather than the manual result extraction vptheron describes, you can use play.api.test.Helpers:

import play.api.test.Helpers._
val result: Future[SimpleResult] = …
val bodyAsBytes: Array[Byte] = contentAsBytes(result)

There's also contentAsString etc.

查看更多
▲ chillily
3楼-- · 2019-04-05 13:20

Building on the answer by Huw, here is the full working code:

import play.api.test._  
def getStringFromAction(action:Action[AnyContent]):String = {
  val request = new FakeRequest("fakeMethod", "fakeUrl", new FakeHeaders, "fakeBody")
  val result = action.apply(request).run
  import scala.concurrent.duration._
  Helpers.contentAsString(result)(1000 millis)
}

You will need to include the following libraries (not included by default in Play): play-test_2.11.jar, selenium-java.jar, selenium-api.jar, selenium-chrome-driver.jar, selenium-firefox-driver.jar, selenium-remote-driver.jar, selenium-htmlunit-driver.jar, fluentlenium-core.jar, htmlunit-core-js.jar and htmlunit.jar. These are available in the Play or Activator distribution. You can also add a dependency in build.sbt as explained here.

查看更多
不美不萌又怎样
4楼-- · 2019-04-05 13:23

Action does not have a content since it's an object that you can use to apply a Request and get a result.

val request: Request[A] = ... // create a request instance
val resultFuture: Future[SimpleResult] = simple(request)

val bodyAsBytes: Array[Byte] = Await.result(Await.result(resultFuture, timeout.duration).body |>>> Iteratee.consume[Array[Byte]](), timeout.duration)

Note that for your example an empty request is enough since you don't use it.

Also, notice that body from SimpleResult is an Enumerator, you need to apply an Iteratee to it, here I'm just applying a consumer to get the whole list. The 2 Await.result are used:

  1. to wait for the Future[SimpleResult] to be complete
  2. to wait for the Enumerator to be done sending data to the Iteratee.
查看更多
登录 后发表回答