Scala/Play framework

Play Framework 2.5. Http 서비스 호출을 위한 WSClient

partner_jun 2017. 4. 19. 13:54

AJAX의 크로스도메인 제약을 넘어서기 위해 CORS가 제시되었지만 여러 이유로 아직까지 서버에서 다른 서버로 요청하고 그 결과를 클라이언트에게 전달하는 방법을 주로 구현한다. 그 구현에 사용되는 라이브러리도 다양한데, JSOUP같은 범용적인 라이브러리도 있지만 Spring에서 주로 RestTemplate를 사용해 Java Bean으로 결과를 매핑해 사용한다.

Play Framework에서는 JSOUP와 유사한 WSClient를 사용하는 것을 권장하고 있다.



1. 기본

WSClient를 사용하려면 먼저 디펜전시를 추가해야 한다.

libraryDependencies ++= Seq(ws)


디펜전시를 추가하면 WSClient 객체를 주입 받아 바로 사용 할 수 있다.

import play.api.mvc._
import javax.inject.{Inject, Singleton}
import play.api.libs.ws.{WSClient, WSResponse}
import scala.concurrent.{ExecutionContext, Future}

@Singleton
class SimpleController @Inject()(ws: WSClient)
(implicit ec: ExecutionContext) extends Controller {

def index = Action.async { implicit req =>
val response: Future[WSResponse] = ws.url("http://www.naver.com").get()
response.map{v =>
Ok(v.body)
}
}

}

WSClient 객체를 주입받아 네이버 url로 접속하고 결과를 받아오는 방법.

Future[Result] 를 반환하는 함수를 전달받는 Action.async를 사용했다.




2. WSRequest, WSResponse

WSClient의 url 메소드를 호출하면 WSRequest 클래스의 객체가 반환된다. 이 때 url 메소드에는 절대주소로 이루어진 URL을 입력해야 한다. 

WSRequest 객체에는 다시 WSRequest 객체를 반환하는 with~ 형태의 메소드와 Future[WSResponse]를 반환하는 execute, get, post 등의 메소드가 있다.

def index = Action.async { implicit req =>
val url: String = routes.SimpleController.postIndex().absoluteURL()
val response: Future[WSResponse] = ws.url(url)
.withQueryString("name" -> "jack")
.execute("POST")

response.map{v =>
Ok(v.body)
}
}

// POST 요청을 위한 함수
def postIndex = Action {req =>
val name = req.getQueryString("name").getOrElse("")
Ok("hello " + name)
}

get()이나 post(body)같은 함수 외에도 execute(method) 함수를 사용 할 수도 있다.

execute 함수에는 Request Method를 대문자로 적어야 한다.




2. WSResponse to JsValue

json 메소드를 사용하면 WSResponse를 JsValue 객체로 변환 할 수 있다.

def index = Action.async { implicit req =>
val url: String = routes.SimpleController.postIndex().absoluteURL()
val response: Future[WSResponse] = ws.url(url)
.withQueryString("name" -> "jack")
.execute("POST")

response.map{v =>
val message = (v.json \ "message").as[String]

Ok(message) // "Hello!"
}
}

// POST 요청을 위한 함수
def postIndex = Action {req =>
val name = req.getQueryString("name").getOrElse("")
val data = Json.obj(
"message" -> "Hello!",
"name" -> name
)

Ok(data)
}