Play アプリケーションから他の HTTP サービスを呼び出したくなることがあります。Play は非同期の HTTP 呼び出しを実現する WS ライブラリ でこれをサポートしています。
WS API には、リクエストの作成とレスポンスの処理という2つの重要な部品があります。まず、GET および POST の HTTP リクエストを作成する方法について紹介し、次に WS からレスポンスを処理する方法について紹介します。最後に、よくあるユースケースを紹介します。
WS を使用するには、まず ws
を build.sbt
ファイルに追加してください。
libraryDependencies ++= Seq(
ws
)
そして、WS を利用したいコントローラやコンポーネントで WSClient
への依存を宣言します。
WSClient
のインスタンスを ws
と名付けたので、以下の例ではこの名前を用いることとします。
HTTP リクエストを構築するには、 WS.url()
を URL を設定して呼び出します。
これは WSRequest を返します。WSRequest はヘッダの設定のような様々な HTTP のオプションを設定するために使用します。メソッド呼び出しを連鎖すると、複雑なリクエストをまとめて構築できます。
最後に、使用したい HTTP メソッドに対応するメソッドを呼び出します。連鎖はこれで終了し、 WSRequest
のリクエストに設定した全てのオプションが使用されます。
すると、 Future[WSResponse]
が返されます。ここで Response がサーバから返されたデータを保持しています。
HTTP 認証を使う必要がある場合には、ビルダーにユーザー名、パスワード、 AuthScheme を設定します。AuthScheme に適用可能なケースオブジェクトは、BASIC
, DIGEST
, KERBEROS
, NONE
, NTLM
そして SPNEGO
です。
もし、HTTP 呼び出しの結果が、302 や 301 のようなリダイレクトである場合には、他のメソッド呼び出しをしなくとも自動的にリダイレクトされます。
パラメーターは、キーと値のタプルで設定します。
ヘッダは、キーと値のタプルで設定します。
もし、プレーンなテキストを特定のフォーマットで送信したいのなら、コンテントタイプを明示的に設定する必要があります。
バーチャルホストは文字列で設定します。
リクエストにタイムアウトを設定する場合には、 withRequestTimeout
を使用しミリ秒で値を設定します。 -1
を設定すると無期限になります。
フォームエンコードされたデータを POST で送信するには、post
に Map[String, Seq[String]]
を渡してください。
JSON データを送信する最も簡単な方法は、 [[JSON|ScalaJson]] ライブラリを使うことです。
XML データを送信する最も簡単な方法は、XML リテラルを使うことです。XML リテラルは便利ですが、それほど速くはありません。効率を重視するなら、XML ビューテンプレート や JAXB ライブラリを使うことを検討してください。
Response に対する操作は Future の中でマッピングをすることで簡単に行えます。
以降の例には、いくつか共通の依存コードがあります。簡潔にするため、ここで1度だけ掲載します。
Future
上で処理を実行するときにはいつでも、暗黙的な実行コンテキストが必要となります。実行コンテキストとは Future
が実行されてコールバックを行うスレッドプールのことです 。通常は、Play のデフォルトの実行コンテキストで充分でしょう。
次の例も、以降のコードで使用するシリアライゼーション、あるいはデシリアラーゼーションのためのケースクラスです。
レスポンスを JSON object として処理するには、response.json
を呼び出します。
JSON ライブラリには、暗黙の Reads[T]
をクラスに直接マッピングする [[便利な機能|ScalaJsonCombinators]] があります。
@scalaws-process-json-with-implicit
レスポンスを XML リテラル として処理するには、response.xml
を呼び出します。
get()
や post()
を実行すると、レスポンスが使用可能になる前に、リクエストボディをメモリに読み込みます。数ギガバイトのファイルのような大量のダウンロードを行うと、不愉快なガベージコレクション、ひいてはアウトオブメモリーエラーを招くかもしれません。
WS では インクリメンタルなレスポンスを [[iteratee|Iteratees]] によって扱うことができます。WSRequest
の stream()
と getStream()
メソッドは Future[(WSResponseHeaders, Enumerator[Array[Byte]])]
を返します。enumerator には レスポンスボディが含まれています。
iteratee を使用して、レスポンスによって返却されたバイト数を数える、ちょっとした例を示します。
もちろん、通常はこのような方法で大きなボディを消費したくはないでしょう。より一般的な使用方法は、ボディを別の場所にストリームによって出力することです。次の例では、ボディをファイルにストリームで出力します。
レスポンスボディの送り先としては他に、このサーバーが現在処理しているレスポンスへのストリームによる出力があります。
POST
と PUT
は、 withMethod
メソッドを明示的に呼び出す必要があります。
for 内包表記は、信頼された環境で WS の呼び出しを連結するのに適しています。起こりうる失敗を処理するには、for 内包表記と一緒に Future.recover を使用してください。
コントローラーからリクエストを作成するときには、レスポンスを Future[Result]
へマッピングできます。これは Play の Action.async
アクションビルダーと組み合わせることで使用できます。詳細は [[非同期レスポンスの処理|ScalaAsync]] にあります。
WSClient は AsyncHttpClient を包むラッパーです。別々のプロファイルを指定した複数のクライアントを定義したり、モックを使用できたりして便利です。
WSによる注入を受けることなく、コードから直接 WS クライアントを定義することができます。そして、 WS.clientUrl()
の際にはクライアントを暗黙的に使用することができます。
NOTE: NingWSClient オブジェクトをインスタンス化した場合には、それは WS モジュールのライフサイクルに乗らないので、
Application.onStop
の際に自動的にはクローズされません。そのかわりに、処理が終了した際にclient.close()
することによりクライアントを手動でシャットダウンしなければなりません。これによって、AsyncHttpClient が内部で使用している ThreadPoolExecutor を開放します。クライアントを閉じることに失敗すると、アウトオブメモリー例外が生じるおそれがあります (特に、開発モードでアプリケーションを頻繁にリロードする場合)。
または直接、
あるいは、マグネットパターンを利用して、特定のクライアントを自動的に紐付けることもできます。
デフォルトでは、設定は application.conf
で行われますが、設定から直接ビルダーを構築することも可能です。
内部の 非同期クライアント を使用することも可能です。
重要な事柄が 2 点あります。WS はクライアントへのアクセス要求時に 2 つの制限があります。
WS
はマルチパートのフォームのアップロードを直接サポートしていません。内部的なクライアントの RequestBuilder.addBodyPart を使用してください。WS
はストリームによるボディのアップロードをサポートしていません。この場合、AsyncHttpClient によって提供されるFeedableBodyGenerator
を使用してください。
WS クライアントの設定は、 application.conf
にある以下のプロパティで行います。
play.ws.followRedirects
: 301、および、302 でのリダイレクトにクライアントが従うかを設定します。 (デフォルトは true)play.ws.useProxyProperties
: システムのHTTPプロキシ設定(http.proxyHost, http.proxyPort)を使用するか設定します。 (デフォルトは true)play.ws.useragent
: User-Agent ヘッダーフィールドを設定します。play.ws.compressionEnabled
: このプロパティが true の場合 gzip/deflater によるエンコーディングを行います。 (デフォルトは false).
HTTP over SSL/TLS (HTTPS) を使用するための WS の設定については、 [[WS SSLの設定|WsSSL]] を参照してください。
WS には3種類のタイムアウト設定があります。タイムアウトになると、WS リクエストが中断します。
play.ws.timeout.connection
: リモートホストとの接続を行う最大の時間です。 ( デフォルトは 120秒 )play.ws.timeout.idle
: アイドル状態(コネクションは確立したが、データを待っている状態)を保持する最大の時間です。 ( デフォルトは 120秒 )play.ws.timeout.request
: リクエストにかかる全体の時間です(リモートホストがデータを送信中であっても、中断する可能性があります)。 ( デフォルトは 120秒 )
リクエストのタイムアウトは withRequestTimeout()
を使用した接続において上書き可能です。 (“リクエストの作成”の節を参照してください。)
内部のAsyncHttpClientConfig にて、以下のような高度な設定を行うことができます。
詳しくはAsyncHttpClientConfig のドキュメントを参照してください。
play.ws.ning.allowPoolingConnection
play.ws.ning.allowSslConnectionPool
play.ws.ning.ioThreadMultiplier
play.ws.ning.maxConnectionsPerHost
play.ws.ning.maxConnectionsTotal
play.ws.ning.maxConnectionLifeTime
play.ws.ning.idleConnectionInPoolTimeout
play.ws.ning.webSocketIdleTimeout
play.ws.ning.maxNumberOfRedirects
play.ws.ning.maxRequestRetry
play.ws.ning.disableUrlEncoding