ドキュメント

§HTTPルーティング

§組み込みHTTPルーター

ルーターは、受信した各HTTPリクエストをアクションに変換する役割を担うコンポーネントです。

HTTPリクエストは、MVCフレームワークによってイベントとして認識されます。このイベントには、次の2つの主要な情報が含まれています。

ルートはコンパイルされるconf/routesファイルで定義されます。これは、ルートエラーがブラウザに直接表示されることを意味します。

§依存性注入

Playのデフォルトのルートジェネレーターは、@Injectアノテーション付きのコンストラクターでコントローラーインスタンスを受け入れるルータークラスを作成します。つまり、このクラスは依存性注入での使用に適しており、コンストラクターを使用して手動でインスタンス化することもできます。

Play 2.7.0より前は、Playはコントローラーをclassではなくobjectとして定義できる静的ルートジェネレーターをサポートしていました。Playはもはや静的状態に依存していないため、これはサポートされなくなりました。独自の静的状態を使用したい場合は、classであるコントローラーで引き続き行うことができます。

§ルートファイルの構文

conf/routesは、ルーターが使用する構成ファイルです。このファイルには、アプリケーションに必要なすべてのルートがリストされています。各ルートは、HTTPメソッドとURIパターンで構成され、両方ともActionジェネレーターの呼び出しに関連付けられています。

ルート定義がどのように見えるかを見てみましょう

GET   /clients/:id          controllers.Clients.show(id: Long)

各ルートは、HTTPメソッドで始まり、その後にURIパターンが続きます。最後の要素は、呼び出しの定義です。

#文字を使用して、ルートファイルにコメントを追加することもできます。

# Display a client.
GET   /clients/:id          controllers.Clients.show(id: Long)

特定のプレフィックスの下で別のルーターを使用するようにルートファイルに指示するには、指定されたプレフィックスの後に“->”を使用します

->      /api                        api.MyRouter

これは、SIRDルーティングとしても知られる文字列補間ルーティングDSLと組み合わせたり、複数のルートファイルを使用してルーティングするサブプロジェクトを操作したりする場合に特に役立ちます。

また、ルートの先頭に+で始まる行を付けることで、修飾子を適用することもできます。これにより、特定のPlayコンポーネントの動作を変更できます。このような修飾子の1つは、CSRFフィルターをバイパスする「nocsrf」修飾子です。

+ nocsrf
POST  /api/new              controllers.Api.newThing

§HTTPメソッド

HTTPメソッドは、HTTP(GETPATCHPOSTPUTDELETEHEAD)でサポートされている有効なメソッドのいずれかになります。

§URIパターン

URIパターンは、ルートのリクエストパスを定義します。リクエストパスの一部を動的にすることができます。

§静的パス

たとえば、受信したGET /clients/allリクエストに完全に一致させるには、このルートを定義できます

GET   /clients/all          controllers.Clients.list()

§動的部分

IDでクライアントを取得するルートを定義する場合は、動的な部分を追加する必要があります

GET   /clients/:id          controllers.Clients.show(id: Long)

注意:URIパターンには、複数の動的な部分を含めることができます。

動的な部分のデフォルトのマッチング戦略は、正規表現[^/]+で定義されています。つまり、:idとして定義された動的な部分は、正確に1つのURIパスセグメントと一致します。他のパターンタイプとは異なり、パスセグメントは、コントローラーに渡される前にルートで自動的にURIデコードされ、逆ルートでエンコードされます。

§複数の/にまたがる動的な部分

動的な部分が、スラッシュで区切られた複数のURIパスセグメントをキャプチャする場合は、*id構文(ワイルドカードパターンとも呼ばれます)を使用して動的な部分を定義できます。これは、.*正規表現を使用します

GET   /files/*name          controllers.Application.download(name)

ここで、GET /files/images/logo.pngのようなリクエストの場合、name動的部分はimages/logo.pngの値をキャプチャします。

複数の/にまたがる動的な部分は、ルーターによってデコードされず、逆ルーターによってエンコードされないことに注意してください。ユーザー入力の場合と同じように、生のURIセグメントを検証するのはあなたの責任です。逆ルーターは単に文字列連結を行うだけなので、結果のパスが有効であり、たとえば複数の先頭のスラッシュや非ASCII文字が含まれていないことを確認する必要があります。

§カスタム正規表現を使用した動的な部分

$id<regex>構文を使用して、動的な部分に独自の正規表現を定義することもできます

GET   /items/$id<[0-9]+>    controllers.Items.show(id: Long)

ワイルドカードルートと同様に、パラメーターはルーターによってデコードされず、逆ルーターによってエンコードされません。そのコンテキストで意味をなすように入力を検証するのはあなたの責任です。

§アクションジェネレーターメソッドの呼び出し

ルート定義の最後の部分は、呼び出しです。この部分では、play.api.mvc.Action値を返すメソッドへの有効な呼び出しを定義する必要があります。通常、これはコントローラーのアクションメソッドになります。

メソッドがパラメーターを定義しない場合は、完全修飾メソッド名を指定するだけです

GET   /                     controllers.Application.homePage()

アクションメソッドがパラメーターを定義している場合、これらのパラメーター値はすべて、リクエストURIで検索されます。URIパス自体から抽出されるか、クエリ文字列から抽出されます。

# Extract the page parameter from the path.
GET   /:page                controllers.Application.show(page)

または

# Extract the page parameter from the query string.
GET   /                     controllers.Application.show(page)

これは、controllers.Applicationコントローラーの対応するshowメソッド定義です

def show(page: String) = Action {
  loadContentFromDatabase(page)
    .map { htmlContent => Ok(htmlContent).as("text/html") }
    .getOrElse(NotFound)
}

§パラメーター型

String型のパラメーターの場合、パラメーターの型指定はオプションです。Playが受信したパラメーターを特定のScala型に変換する場合は、パラメーターを明示的に型指定できます

GET   /clients/:id          controllers.Clients.show(id: Long)

そして、controllers.Clientsコントローラーの対応するshowメソッド定義でも同様に行います

def show(id: Long) = Action {
  Client
    .findById(id)
    .map { client => Ok(views.html.Clients.display(client)) }
    .getOrElse(NotFound)
}

Playは、次のパラメーター型をサポートしています

別の型があり、それを実装する場合は、リクエストバインダーを参照してください

§固定値を持つパラメーター

パラメーターに固定値を使用したい場合があります

# Extract the page parameter from the path, or fix the value for /
GET   /                     controllers.Application.show(page = "home")
GET   /:page                controllers.Application.show(page)

§デフォルト値を持つパラメーター

受信したリクエストで値が見つからない場合に使用されるデフォルト値を指定することもできます

# Pagination links, like /clients?page=3
GET   /clients              controllers.Clients.list(page: Int ?= 1)

§オプションのパラメーター

すべてのリクエストに存在する必要のないオプションのパラメーターを指定することもできます

# The version parameter is optional. E.g. /api/list-all?version=3.0
GET   /api/list-all         controllers.Api.list(version: Option[String])

§リストパラメーター

繰り返されるクエリ文字列パラメーターにリストパラメーターを指定することもできます

# The item parameter is a list.
# E.g. /api/list-items?item=red&item=new&item=slippers
GET   /api/list-items      controllers.Api.listItems(item: List[String])
# or
# E.g. /api/list-int-items?item=1&item=42
GET   /api/list-int-items  controllers.Api.listIntItems(item: List[Int])

§ルーティング優先度

多くのルートが同じリクエストに一致する可能性があります。競合がある場合は、最初のルート(宣言順)が使用されます。

§逆ルーティング

ルーターは、Scala呼び出し内からURLを生成するためにも使用できます。これにより、すべてのURIパターンを単一の構成ファイルに集中させることができるため、アプリケーションをリファクタリングするときに自信を持つことができます。

ルートファイルで使用されるコントローラーごとに、ルーターはroutesパッケージに「逆コントローラー」を生成します。このコントローラーは、同じアクションメソッドを持ち、署名は同じですが、play.api.mvc.Actionではなくplay.api.mvc.Callを返します。

play.api.mvc.CallはHTTP呼び出しを定義し、HTTPメソッドとURIの両方を提供します。

たとえば、次のようなコントローラーを作成した場合

package controllers
  import javax.inject.Inject

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

  class Application @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
    def hello(name: String) = Action {
      Ok("Hello " + name + "!")
    }
  }

conf/routesファイルにそれをマップした場合

# Hello action
GET   /hello/:name          controllers.Application.hello(name)

次に、controllers.routes.Application逆コントローラーを使用して、helloアクションメソッドへのURLを反転させることができます

// Redirect to /hello/Bob
def helloBob = Action {
  Redirect(routes.Application.hello("Bob"))
}

注: 各コントローラーパッケージには routes サブパッケージが存在します。したがって、アクション controllers.Application.hello は、controllers.routes.Application.hello を介してリバースできます(routes ファイル内で、生成されたパスに一致する別のルートがその前にない場合に限ります)。

リバースアクションメソッドは非常に単純に機能します。パラメータを受け取り、それらをルートパターンに代入します。パスセグメント(:foo)の場合、値は代入が行われる前にエンコードされます。正規表現およびワイルドカードパターンについては、値が複数のセグメントにまたがる可能性があるため、文字列は生の形式で代入されます。リバースルートに渡す際に、これらのコンポーネントを必要に応じてエスケープし、検証されていないユーザー入力を渡さないようにしてください。

§相対ルート

絶対ルートではなく相対ルートを返すことが有用な場合があります。play.mvc.Call によって返されるルートは常に絶対ルート(/ で始まる)であり、WebアプリケーションへのリクエストがHTTPプロキシ、ロードバランサー、およびAPIゲートウェイによって書き換えられる場合に問題を引き起こす可能性があります。相対ルートの使用が有用な例を以下に示します。

相対ルートを生成できるようにするには、ターゲットルートを相対化する基準(開始ルート)を知る必要があります。開始ルートは現在の RequestHeader から取得できます。したがって、相対ルートを生成するには、現在の RequestHeader または開始ルートを String パラメータとして渡す必要があります。

例えば、次のようなコントローラーエンドポイントがある場合

package controllers

import javax.inject._

import play.api.mvc._

@Singleton
class Relative @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
  def helloview: Action[AnyContent] = Action { implicit request => Ok(views.html.hello("Bob")) }

  def hello(name: String): Action[AnyContent] = Action {
    Ok(s"Hello $name!")
  }
}

注: 現在のリクエストは、implicit request を宣言することで、ビューテンプレートに暗黙的に渡されます。

conf/routesファイルにそれをマップした場合

GET     /foo/bar/hello              controllers.Relative.helloview
GET     /hello/:name                controllers.Relative.hello(name)

これまでと同様にリバースルーターを使用して相対ルートを定義し、relative への追加呼び出しを含めることができます。

@(name: String)(implicit request: RequestHeader)

<h1>Hello @name</h1>

<a href="@routes.Relative.hello(name)">Absolute Link</a>
<a href="@routes.Relative.hello(name).relative">Relative Link</a>

注: コントローラーから渡された RequestRequestHeader にキャストされ、ビューパラメータで implicit とマークされます。その後、relative への呼び出しに暗黙的に渡されます。

/foo/bar/hello をリクエストすると、生成されるHTMLは次のようになります。

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Bob</title>
    </head>
    <body>
      <a href="/hello/Bob">Absolute Link</a>
      <a href="../../hello/Bob">Relative Link</a>
    </body>
</html>

§デフォルトコントローラー

Playには、便利なアクションをいくつか提供する Default コントローラーが含まれています。これらはroutesファイルから直接呼び出すことができます。

# Redirects to https://play.dokyumento.jp/ with 303 See Other
GET   /about      controllers.Default.redirect(to = "https://play.dokyumento.jp/")

# Responds with 404 Not Found
GET   /orders     controllers.Default.notFound

# Responds with 500 Internal Server Error
GET   /clients    controllers.Default.error

# Responds with 501 Not Implemented
GET   /posts      controllers.Default.todo

この例では、GET /about は外部Webサイトにリダイレクトしますが、別のアクション(上記の例では /posts など)にリダイレクトすることも可能です。

§カスタムルーティング

Playには、_String Interpolating Routing DSL_、略してSIRDと呼ばれる組み込みルーターを定義するためのDSLが用意されています。このDSLには、軽量のPlayサーバーの埋め込み、通常のPlayアプリケーションへのカスタムまたはより高度なルーティング機能の提供、テスト用のRESTサービスのモックなど、多くの用途があります。

String Interpolating Routing DSL を参照してください。

次へ: HTTP結果の操作


このドキュメントに誤りを見つけましたか?このページのソースコードは こちら にあります。 ドキュメントのガイドライン を読んだ後、プルリクエストを自由に貢献してください。質問や共有するアドバイスがありますか? コミュニティフォーラム にアクセスして、コミュニティとの会話を始めましょう。