I'm quite new to Scala
I'm trying to access Instagram API from Play! and Scala.
def authenticate = Action {
request =>
request.getQueryString("code").map {
code =>
WS.url("https://api.instagram.com/oauth/access_token")
.post(
Map("client_id" -> Seq(KEY.key), "client_secret" -> Seq(KEY.secret), "grant_type" -> Seq("authorization_code"),
"redirect_uri" -> Seq("http://dev.my.playapp:9000/auth/instagram"), "code" -> Seq(code))
) onComplete {
case Success(result) => Redirect(controllers.routes.Application.instaline).withSession("token" -> (result.json \ "access_token").as[String])
case Failure(e) => throw e
}
}
Redirect(controllers.routes.Application.index)
}
When app executes, the last redirect happens before redirect in case of Success.
Tell me please, how to avoid it. And Also, let me know about bad practices that is in my code.
With Play, you return a result - you don't send a result. The onComplete
method attaches a method that does something, but doesn't return anything (note its return value is Unit
, ie, void
). After attaching that callback, you are then returning Redirect
on the last line, which is not what you want to do. Instead you want to map
the future that you get back from the WS invocation, and return that future. And to return a future in Play, you need to use the Action.async
builder. eg:
def authenticate = Action.async { request =>
request.getQueryString("code").map { code =>
WS.url("https://api.instagram.com/oauth/access_token").post(
Map(
"client_id" -> Seq(KEY.key),
"client_secret" -> Seq(KEY.secret),
"grant_type" -> Seq("authorization_code"),
"redirect_uri" -> Seq("http://dev.my.playapp:9000/auth/instagram"),
"code" -> Seq(code)
)
).map { result =>
Redirect(controllers.routes.Application.instaline)
.withSession("token" -> (result.json \ "access_token").as[String])
}
}.getOrElse {
Future.successful(Redirect(controllers.routes.Application.index))
}
}