やりたいこと
通常のActionを利用するとこんな感じ
def hoge(mage: Int) = Action(parse.json) {
// do something
Ok
}
いい感じの認証用Actionを用意して、認証失敗なら共通のレスポンスを自分で設定したい
(Jsonを出力するとか)
// 認証が通らなければ {"auth" -> "failed"} を返す
def hoge(mage: Int) = AuthAction(parse.json) {
// do something
Ok(Json.obj("auth" -> "success"))
}
独自Actionを作る
まずはActionBuilderを継承したobjectを適当な所に作る
import play.api.mvc.{ActionBuilder, Request}
import scala.concurrent.Future
object AuthAction extends ActionBuilder[Request] {
// invokeBlockはabstractなので、実装しないといけない
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
// do anything
}
当然何も返さないと怒られるので、レスポンスを用意してあげる。
import play.api.mvc.{ActionBuilder, Request}
import scala.concurrent.Future
object AuthAction extends ActionBuilder[Request] {
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
println("hogehoge")
block.apply(request)
}
試しにこのAuthActionを使えば処理は何も変わらないけどhogehogeがコンソールに表示されていることを確認できる。
認証処理
sessionを使った適当な認証を書いてみる
import play.api.mvc.{ActionBuilder, Request}
import scala.concurrent.Future
object AuthAction extends ActionBuilder[Request] {
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
request.session.get("foo") == "bar" match {
case true => // 認証OK
case _ => // 認証NG
}
block.apply(request)
}
自分でレスポンスを設定
あとは認証失敗時のレスポンスを自分で作れればOK
import play.api.mvc.{Results, ActionBuilder, Request, Result}
import scala.concurrent.Future
import play.api.libs.json.Json
object AuthAction extends ActionBuilder[Request] {
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
request.session.get("foo") == "bar" match {
case true => block.apply(request)
case _ => Future.successful(Results.Status(401).apply(Json.obj("auth" -> "failed")))
}
}
Unauthorized ... Results.Status(401).apply() という事になるので、
出てきたResultを適当にFutureで包んであげればよいことになる
これで要認証Actionと認証不要Actionを手軽に使い分けられる