Zuriar
Zuriar

Reputation: 11774

How does a play.api.mvc.Action actual return a Result?

In the play framework (scala) docs (http://www.playframework.com/documentation/2.2.x/ScalaActions) it says:

A play.api.mvc.Action is basically a (play.api.mvc.Request => play.api.mvc.Result) function that handles a request and generates a result to be sent to the client.

val echo = Action { request =>
  Ok("Got request [" + request + "]")
}

An action returns a play.api.mvc.Result value, representing the HTTP response to send to the web client. In this example Ok constructs a 200 OK response containing a text/plain response body.

Now, when I create that echo val (as above) at the console I don't get a Result value as suggested but an Action[AnyContent]

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

What is going on here? Is there an error in the documentation?

Upvotes: 4

Views: 3688

Answers (1)

Zarkus13
Zarkus13

Reputation: 302

In fact, if you look at the code of Action : https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/mvc/Action.scala

val echo = Action { request =>
  Ok("Got request [" + request + "]")
}

This calls the apply method of Action that indeed returns a new Action :

/**
 * Constructs an `Action` with default content.
 *
 * For example:
 * {{{
 * val echo = Action { request =>
 *   Ok("Got request [" + request + "]")
 * }
 * }}}
 *
 * @param block the action code
 * @return an action
 */
final def apply(block: R[AnyContent] => Result): Action[AnyContent] = 
    apply(BodyParsers.parse.anyContent)(block)

Then :

/**
 * Constructs an `Action`.
 *
 * For example:
 * {{{
 * val echo = Action(parse.anyContent) { request =>
 *   Ok("Got request [" + request + "]")
 * }
 * }}}
 *
 * @tparam A the type of the request body
 * @param bodyParser the `BodyParser` to use to parse the request body
 * @param block the action code
 * @return an action
 */
final def apply[A](bodyParser: BodyParser[A])(block: R[A] => Result): Action[A] =   
  async(bodyParser) { req: R[A] =>
    block(req) match {
      case simple: SimpleResult => Future.successful(simple)
      case async: AsyncResult => async.unflatten
    }
}

In fact, later, the framework will call an other apply method of the Action you created, by passing a Request parameter :

/**
 * Invokes this action.
 *
 * @param request the incoming HTTP request
 * @return the result to be sent to the client
 */
def apply(request: Request[A]): Future[SimpleResult]

For example :

echo(request)

This method will then return a Result, the one you returned previously in

val echo = Action { request =>
  Ok("Got request [" + request + "]")
}

I hope I was clear enough !

Upvotes: 4

Related Questions