Playã«ã¯ãHTTPéä¿¡ããããã®ã©ã¤ãã©ãªãç¨æããã¦ã¾ãã
play.api.libs.ws.WS ã¨ãããã¤ã§ããã
ããã¥ã¡ã³ãã«ãããéããããã使ãã°æéããããã§ãããHTTPéä¿¡ãéåæã«è¡ããã¨ãã§ãã¾ãã
http://www.playframework-ja.org/documentation/2.0.4/ScalaWS
WS ã使ã£ã¦RSSãåå¾ãã¦ã¿ã¾ããã
使ã£ãã®ã¯Play2.1.1ã§ãã
GETãªã¯ã¨ã¹ããã
以ä¸ã®ããã«ãGETãªã¯ã¨ã¹ãã§ãã¾ããçµæã¯Futureã§è¿ã£ã¦ãã¾ãã
val rss: Future[ws.Response] = WS.url("http://example1/atom.xml").get()
Futureãåãã£ã¦ã人ã¯ããããã§çµããã§ãã
ã§ããããã¯Futureãããåãã£ã¦ãªãã®ã§ã1ã¤ãã¤è§£ãã»ããã¦ããå¿ è¦ãããã¾ãã
WS API ã¯éåæã§HTTPéä¿¡ãããããget()ã¡ã½ãããå¼ã³åºãã¨Futureãªãã¸ã§ã¯ããã¨ããããè¿ãã¦ãã¾ãã
ãã®æãHTTPéä¿¡ã¯ã¾ã çµãã£ã¦ãã¾ããã
HTTPéä¿¡ãçµãã£ã¦ãªãã¦ããã¨ããããFutureãªãã¸ã§ã¯ããè¿ã£ã¦ããã®ã§æ¬¡ã®å¦çã«é²ããã¨ãã§ãã¾ãã
GETãªã¯ã¨ã¹ãã®çµæã使ã
ããããRSSãåå¾ãã¦ãããããã®ã¾ã¾è¿ããããªActionãä½ã£ã¦ã¿ã¾ãã
å
ã«è¨ã£ã¦ããã¨ãä¸ã®ä¾ã¯è¯ããªãããæ¹ã§ãã
import play.api.libs.ws import play.api.libs.ws.WS import scala.concurrent._ import ExecutionContext.Implicits.global import scala.concurrent.duration.Duration object Application extends Controller { def index = Action { val rss: Future[ws.Response] = WS.url("http://example1/atom.xml").get() val response: ws.Response = Await.result(rss, Duration(1000, MILLISECONDS)) Ok(response.body) } }
RSSãåå¾ããããã®HTTP GETã«å¯¾ããã¬ã¹ãã³ã¹ãåå¾ãã¾ãã
ã¤ã¾ããFutureã®ä¸èº«ã«ããws.Responseãªãã¸ã§ã¯ããåå¾ãã¾ãã
ããã«ã¯ãAwait.restult()ã使ãã¾ãã
HTTPéä¿¡ãéåæã§è¡ããããããAwait.result()ãå¼ã³åºããæã«ã¯ãã¾ã HTTPéä¿¡ãçµãã£ã¦ãªãå¯è½æ§ãããã¾ãã
ä¸ã®ä¾ã§ã¯ã1000ããªç§ä»¥å
ã«HTTPéä¿¡ãçµããã°ã¬ã¹ãã³ã¹ãåå¾ã§ãã1000ããªç§ä»¥å
ã«HTTPéä¿¡ãçµãããªãå ´åã¯TimeoutExceptionãçºçãã¾ãã
ã¬ã¹ãã³ã¹ãåå¾ã§ããããã¬ã¹ãã³ã¹ããã£ããã®ã¾ã¾Ok()ã«æå®ãã¦ãã¾ãã
ï¼Ok()ã¯SimpleResultãªãã¸ã§ã¯ããçæããããã®ã¡ã½ããã§ããï¼
ã¨ããã§ã
import ExecutionContext.Implicits.global
ã¨ãããããªè¬ã®importæãããã¾ãããããã¯Futureãªãã¸ã§ã¯ãã®ã¡ã½ãããImplicitãã©ã¡ã¼ã¿ãåãåãããã«ãªã£ã¦ããã®ããã£ã¦ããã®ããã§ãã
Futureãªãã¸ã§ã¯ãã®ã»ã¨ãã©ã®ã¡ã½ããã¯Implicitãã©ã¡ã¼ã¿ãå¿
è¦ãªã®ã§ãFutureã使ãã¨ãã¯importãã¦ãããæ¹ãããããã§ãã
AsyncResultã使ã
ãã£ããè¨ãã¾ããããAwaitã§ã¬ã¹ãã³ã¹ãåå¾ããã®ã¯è¯ããªãããæ¹ã§ãã
ãã£ããæéãæãããããªHTTPéä¿¡ãéåæå¦çã«ãã¦ããã£ãã¨æ¬¡ã®å¦ç移ãããããªä»çµã¿ãªã£ã¦ãã®ã«ãçµå±Futureããçµæãåå¾ããããã«ã1000ããªç§å¾
ã£ã¦ããããã§ãã
ãããããéåæã«ãã¦ãæå³ããªãã
ããã§ç»å ´ããã®ããControllerã§å®ç¾©ããã¦ããAsync() ã
ããã¤ã¯ãFuture[Result]ãåãåã£ã¦AsyncResultãè¿ãã¾ãã
AsyncResultã¯ãOkã§çæããSimpleResultã¨åæ§ã«ãResultã®åã¯ã©ã¹ãªã®ã§Actionã®çµæã«ä½¿ãã¾ãã
Async()ãå©ç¨ããããã«ãWS API ã§æã«å
¥ããFuture[ws.Response]ããws.Responseãåãåºãã¦ãFuture[Result]ã«å¤æããå¿
è¦ãããã¾ãã
ããã¯ãList("1", "2", "3").map{ s => s.toInt } ã¨ããããã«List[String]ããList[Int]ã«å¤æããã®ã¨åãã§ãã
Futureã«ãmapãå®ç¾©ããã¦ããã®ã§ã以ä¸ã®ããã«æ¸ãã¾ãã
val rss: Future[ws.Response] = WS.url("http://example1/atom.xml").get() rss map { response => Ok(response.body) }
ããã§Future[Result]ãæã«å ¥ãã®ã§ãAsyncã¸æ¸¡ãããã«ãã¾ãã
def index = Action { Async { val rss: Future[ws.Response] = WS.url("http://example1/atom.xml").get() rss map { response => Ok(response.body) } } }
ä¾å¤ããã³ããªã³ã°ãã
é©å½ãªURLãæå®ããå ´åãªã©ãFutureããws.Responseãåå¾ãããã¨ããã¨ãã«ãä¾å¤ãçºçãã¾ãã
çºçããä¾å¤ããã³ããªã³ã°ãã¦ã¿ã¾ãã
Futureã®recover()ã¡ã½ããã使ããã¨ã§ä¾å¤ããã³ããªã³ã°ã§ãã¾ãã
def index = Action { Async { val rss: Future[ws.Response] = WS.url("http://example1/atom.xml").get() rss map { response => Ok(response.body) } recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
2ã¤ã®RSSãåå¾ãã
2ã¤ã®RSSãåå¾ãã¦ä¸¡æ¹ã®ã¬ã¹ãã³ã¹ã使ã£ã¦çµæãè¿ãããå ´åã®è©±ã§ãã
val rss1 = WS.url("http://example1/atom.xml").get() val rss2 = WS.url("http://example2/atom.xml").get()
2ã¤ã®Futureãªãã¸ã§ã¯ãã使ãã°ããã®ã§ãããä¸ã®ããã«åç´ã«å ¥ãåã«ãã¦ããã¡ã§ããã
def index = Action { Async { val rss1 = WS.url("http://example1/atom.xml").get() val rss2 = WS.url("http://example2/atom.xml").get() rss1 map { response1 => rss2 map { response2 => Ok(response.body) } } recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
mapã®å®ç¾©ä¸ãws.Response => Result ã¨ããé¢æ°ã«ããå¿
è¦ãããã¾ãããä¸è¨ã®ããã«å
¥ãåã«ãã¦ãã¾ãã¨ãws.Response => Future[Result] ã¨ãªã£ã¦ãã¾ãã¾ãã
res1 map { ã»ã»ã» } ã®çµæã¯ãFuture[Future[Result]]ã«ãªã£ã¦ãã¾ãã¾ãã
ãããªæã¯flatMapã
ããã¯ãListãªã©ã®æä½ã¨ãã£ããã§ãã
scala> List(1,2,3) map { x => List(1,2) map( x * _) } res1: List[List[Int]] = List(List(1, 2), List(2, 4), List(3, 6)) scala> res1.flatten res2: List[Int] = List(1, 2, 2, 4, 3, 6) scala> List(1,2,3) flatMap { x => List(1,2) map( x * _) } res3: List[Int] = List(1, 2, 2, 4, 3, 6)
ãããããã£ãã®mapãå ¥ãåã«ãããã¤ããflatMapã§æ¸ãæãã¦ã¿ã¾ãã
def index = Action { Async { val rss1 = WS.url("http://example1/atom.xml").get() val rss2 = WS.url("http://example2/atom.xml").get() rss1 flatMap { response1 => rss2 map { response2 => Ok(response1.body + "\n\n" + response2.body) } } recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
ããã§2ã¤ã®Futureãçµã¿åããããã¨ãã§ãã¾ããã
ã¡ãªã¿ã«ãFutureã¯map, flatMapãå®ç¾©ãã¦ããã®ã§ä»¥ä¸ã®ããã«forå¼ã§æ¸ããã¨ãã§ãã¾ãã
è¤æ°åã®Futureãçµã¿åããã¦å
¥ãåãæ·±ããªããªãforå¼ã®æ¹ãè¦ãããã§ãã
def index = Action { Async { val rss1 = WS.url("http://example1/atom.xml").get() val rss2 = WS.url("http://example2/atom.xml").get() val f = for { response1 <- rss1 response2 <- rss2 } yield Ok(response1.body + "\n\n" + response2.body) f recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
ããã§2å以ä¸ã®Futureã§ãæ±ãããã§ãã
nåã®RSSãåå¾ãã
å
ç¨ã®ä¾ã ã¨ãåå¾ããRSSã®åæ°ã2ã¤ã§æ±ºã¾ã£ã¦ãã¾ããã
Futureãªãã¸ã§ã¯ãã®åæ°ãåçãªå ´åãforå¼ã¯ä½¿ããªãããã§ãã
ããã§ãFutureã«å®ç¾©ããã¦ãFuture.sequenceã使ãã¾ãã
Future.sequenceã«Seq[Future[ws.Response]]ã渡ãã¨ãFuture[Seq[ws.Response]ã«å¤æãã¦ããã¾ãã
def index = Action { Async { val urls: Seq[String] = ã»ã»ã» val fs: Seq[Future[ws.Response]] = urls.map(WS.url(_)) val f = Future.seqence(fs) map { responses => Ok(responses.map(_.body).mkString("\n\n") } f recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
nåã®RSSããã¹ã¦åå¾ãããmapå
ã®å¦çãè¡ãã¾ãã
ããã§nåã®RSSãæ±ãã¾ããã
ã¡ãªã¿ã«ãFuture.traverseã使ã£ã¦ãæ¸ãã¾ãã
def index = Action { Async { val urls: Seq[String] = ã»ã»ã» val fs: Future[Seq[ws.Response]] = Future.traverse(urls)( WS.url(_).get) val f = fs map { responses => Ok(responses.map(_.body).mkString("\n\n") } f recover { case e: java.net.ConnectException => Ok("RSSãåå¾ã§ãã¾ããã§ãã") } } }
ããã¾ã
ãããªæãã§RSSãåå¾ãã¦ã¿ã¾ããã
Futureã«ã¤ãã¦ã¯ä»¥ä¸ã®ãµã¤ããåãããããã£ãã§ãã
http://docs.scala-lang.org/ja/overviews/core/futures.html