お久しぶりです。開発部のYanagitaです。
宮崎は相変わらず蒸し暑い日が続いていて、ゲリラ豪雨に悩まされた頃が少し恋しくも感じてます。
私の回はこれまでPlay Frameworkについて記事をいくつか書きましたが、
ブログの担当が回ってくるまでの間にPlay Frameworkのバージョンが2.5系から2.6系へ上がったので、
今回は2.6にアップデートされたPlay Frameworkの更新内容についてチェックしたいと思います。
(Play Frameworkを開発する会社の社名もTypesafe社からLightbend社に変わってましたね)
Play Framework 2.6の更新内容
以下、Play FrameworkはPlayと記述します。
Scala 2.12のサポート
Play2.6もScala2.12に対応しました。
Scala2.12へのアップデートを検討している弊社開発チームとしてはとても大きなアップデートの一つです。
Play2.6はScala2.11にも対応しているため、build.sbtの記述を変更するとこでScalaのバージョンを変更できます。
Scala 2.12の場合(デフォルト)
scalaVersion := "2.12.2"
Scala 2.11の場合
scalaVersion := "2.11.11"
グローバルステートへのアクセス制限
Play2.6ではアプリケーションからplay.api.Play.current/play.Play.application()へのアクセスが非推奨となっています。
以下の設定を行うことで呼び出し時に例外をスローすることができます。
play.allowGlobalApplication=false
Akka HTTPの採用
これまでWebサーバとしてバックエンド部分にデフォルトでNettyが使用されていましたが、Play2.6からAkka HTTPに変更となります。
一応、これまで標準のNettyもサポートを続けていますのでNettyを使用する場合はbuild.sbtの記述を変更できます。
lazy val root = (project in file(".")) .enablePlugins(PlayScala, PlayNettyServer) .disablePlugins(PlayAkkaHttpServer)
起動時に使用するサーバをNettyに変更することもできます。
sbt run -Dplay.server.provider=play.core.server.NettyServerProvider
HTTP/2サポート(実験的)
HTTP/2への対応が行われました。ただし、これはAkka Http側の仕様(API)が変更される可能性があるため実験的とされています。
また、テストも完全ではないため実使用はもうしばらく避けたほうが良さそうです。
HTTP/2の有効化
lazy val root = (project in file(".")) .enablePlugins(PlayJava, PlayAkkaHttp2Support)
リクエスト属性の追加
リクエスト内にタグを情報として格納していましたが非推奨となり、Play2.6からは属性として格納することが薦められています。
例
// 属性名と格納するオブジェクトを宣言 object Attrs { val User: TypedKey[User] = TypedKey.apply[User]("user") } // リクエスト情報から属性値を取得 val user: User = req.attrs(Attrs.User) // リクエスト情報に属性を追加 val newReq = req.addAttr(Attrs.User, newUser)
Route modifiersタグ
route単位にタグを指定することで動作の調整が可能となります。
例えば、CSRFフィルターをあるrouteにのみ非適用とする場合に「nocsrf」タグが用意されています。
このタグをrouteの直前に記述することでそのrouteにはCSRFフィルターが適用されません。
+ nocsrf POST /api/foo/bar ApiController.foobar
独自のタグも生成するが可能です。複数タグを設置する場合は、半角空白区切りでタグを並べます。
フィルタの強化
Play2.6ではセキュリティに特化したフィルタがデフォルトでセットされるようになりました。
- play.filters.csrf.CSRFFilter ← CSRFへの対策フィルタ
- play.filters.headers.SecurityHeadersFilter ← XSSとクリックジャッキングの対策フィルタ
- play.filters.hosts.AllowedHostsFilter ← DNSリバインディングの対策フィルタ
独自のフィルタを追加、または無効化する場合はapplication.confに記述します。
フィルタを追加する場合
play.filters.enabled+=MyFilter // 既存フィルタに追加するので「+=」を使用する
フィルタを無効化する場合
play.filters.disabled+=MyFilter
JWT Cookiesの対応
Play2.6では、JSONウェブトークンセッションとフラッシュクッキーをJWT形式に対応しました。
標準化された署名Cookieデータ、有効期限、署名でより柔軟性を実現しています。
テストの改善
Play2.6ではplay.api.testパッケージに新しいユーティリティクラスが追加されます。
- Injecting
依存注入する際にapp.injector.instanceOfを使用していたが、Injecting traitを使用することで簡潔に書けるようになります。
Play2.5まで
"test" in new WithApplication() { val executionContext = app.injector.instanceOf[ExecutionContext] ... }
Play2.6から
"test" in new WithApplication() with Injecting { val executionContext = inject[ExecutionContext] ... }
* StubControllerComponents
StubControllerComponentsFactoryを利用してControllerComponentsを作成することでコントローラーのテストが可能となります。
val controller = new MyController(stubControllerComponents())
* StubBodyParser
StubBodyParserFactoryを利用してBodyParserを作成することでレスポンスボディのテストが可能となります。
val stubParser = stubBodyParser(AnyContent("hello"))
ファイルアップロード機能の改善
Play2.5までは、TemporaryFileオブジェクトがGCのタイミングでfinalizeを使用してテンポラリに残るファイルを削除してましたが、一定の条件がではGCがタイムリーに行われない問題がありました。
Play2.6からは、その問題を解消するため削除処理をfinalizeからFinalizableReferenceQueueとPhantomReferencesを使用するように変更しました。
また、全てのTemporaryFileはTemporaryFileCreatorを使用するように変更されたため、必要に応じて実装が変更できるようになりました。
それから、Akkaのスケジューラを使用して一時ファイルを削除する機能としてTemporaryFileReaperが用意されました。
TemporaryFileReaperの設定はapplication.confに記述します
play.temporaryFile { reaper { enabled = true initialDelay = "5 minutes" // ← アプリケーション起動後に5分後にTemporaryFileReaperを起動する interval = "30 seconds" // ← TemporaryFileReaper起動後、30秒毎にファイルをチェックする olderThan = "30 minutes" // ← 30分経過したファイルは削除する } }
最後に
いくつか掻い摘んでの説明となりました。 漏れた分についてはまたタイミングをみてやりたいと思います。
詳しく知りたい方はドキュメントが公開されているのでこちらをご確認下さい。
Play Frameworkはマイナーアップデートでも仕様が大きく変わる傾向があるので、今後も変わったところを重点的に紹介して行ければと思います。
弊社では引き続きエンジニア・デザイナーの募集を続けています。
気になる方は下からご応募をお願いします!