Documentation

You are viewing the documentation for the 2.2.0 release in the 2.2.x series of releases. The latest stable release series is 2.4.x.

§リクエストインターセプター

§フィルタの利用

フィルターとは、アプリケーションへ送られてきたリクエストをインターセプト(傍受)したり、リクエストまたはレスポンスに変換処理を行うことを可能にするコンポーネントです。フィルターを使うと、アプリケーションを横断する関心事をうまく実装することができます。フィルターは Filter トレイトを継承して実装され、 Global へ追加されることで機能します。次の例では、全てのアクションの実行結果のログをとるアクセスログフィルターを実装しています。

import play.api.mvc._

object AccessLog extends Filter {
  def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
    val result = next(request)
    play.Logger.info(request + "\n\t => " + result)
    result
  }
}

object Global extends WithFilters(AccessLog)

Global オブジェクトは WithFilters クラスを継承しており、複数のフィルタを渡すとフィルタチェインをつくってくれます。

Note 現在、 WithFiltersGlobalSettings トレイトを継承しています

次の例は非常に有用なフィルタで、アクションの呼び出し前にアクセス認可チェックを行うというものです。

object AuthorizedFilter {
  def apply(actionNames: String*) = new AuthorizedFilter(actionNames)
}

class AuthorizedFilter(actionNames: Seq[String]) extends Filter {

  def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
    if(authorizationRequired(request)) {
      /* do the auth stuff here */
      println("auth required")
      next(request)
    }
    else next(request)
  }

  private def authorizationRequired(request: RequestHeader) = {
    val actionInvoked: String = request.tags.getOrElse(play.api.Routes.ROUTE_ACTION_METHOD, "")
    actionNames.contains(actionInvoked)
  }


}


object Global extends WithFilters(AuthorizedFilter("editProfile", "buy", "sell")) with GlobalSettings {}

Tip RequestHeader.tags には、アクションの呼び出しに利用されたルートに関する有益な情報が色々と含まれています

§onRouteRequest をオーバライドする

Global オブジェクトにはもう一つ重要な側面があります。それは、リクエストをインターセプトする手段を提供してくれる、ということです。これを利用すると、アクションへリクエストが送られる前に任意のビジネスロジックを実行することができます。

Tip このフックは、リクエストをハイジャックして、開発者が任意のリクエストルーティング機構をプラグインする、という用途にも利用できます

早速、これを実践するとどうなるのか見てみましょう。

import play.api._
import play.api.mvc._

// Note: this is in the default package.
object Global extends GlobalSettings {

  override def onRouteRequest(request: RequestHeader): Option[Handler] = {
    println("executed before every request:" + request.toString)
    super.onRouteRequest(request)
  }

}

ここで紹介した方法以外にも、 アクション合成 を使って特定のアクションメソッドだけをインターセプトする、というテクニックもあります。

次ページ: アプリケーションのテスト