Sunday, 24 March 2013

The simplest Async Scala Http Client working with 2.10

This client is not the most efficient or the most async but it works and I am using it for testing my apps. Please feel free to copy/paste/reuse at your own risk.
import concurrent.{Await, ExecutionContext, Future}
import java.net.{HttpURLConnection, URL}
import io.Source
import concurrent.duration.FiniteDuration
case class HttpResponse(code : Int, body: String, headers: Map[String, List[String]])
case class RequestBody(body: String, contentType: String = "text/plain")
object RequestBody{
implicit def toRB(json: String) = RequestBody(json, contentType = "application/json")
}
class Http(baseUrl : String, cookie: Option[String] = None)(implicit ec: ExecutionContext, encoding: String="UTF-8"){
def setCookie(cookie: String) = {
new Http(baseUrl, Some(cookie))
}
import collection.JavaConverters._
def get(path : String ) : Future[HttpResponse] = doRequest("GET", path)
def post(path : String, requestBody: RequestBody ) : Future[HttpResponse] = doRequest("POST", path, Option(requestBody))
def put(path : String, requestBody: RequestBody ) : Future[HttpResponse] = doRequest("PUT", path, Option(requestBody))
def delete(path : String ) : Future[HttpResponse] = doRequest("DELETE", path)
def doRequest(method: String, path: String, requestBody: Option[RequestBody] = None): Future[HttpResponse] = Future {
val con = new URL(baseUrl + path).openConnection().asInstanceOf[HttpURLConnection]
try {
con.setDoInput(true)
con.setInstanceFollowRedirects(false)
cookie.foreach(cookie => con.setRequestProperty("Cookie", cookie))
con.setRequestMethod(method)
requestBody foreach{ requestBody=>
con.setRequestProperty("Content-Type", s"${requestBody.contentType}; charset=$encoding")
con.setDoOutput(true)
val out = con.getOutputStream
out.write(requestBody.body.getBytes(encoding))
out.flush()
out.close()
}
val headers = con.getHeaderFields.asScala.mapValues(_.asScala.toList).toMap - null
val body = Source.fromInputStream(con.getInputStream).getLines() mkString ("\n")
HttpResponse(con.getResponseCode, body, headers)
} finally {
con.disconnect()
}
}
}
view raw Http.scala hosted with ❤ by GitHub

2 comments:

  1. cool, I would recommend to check out dispatch.databinder.net and also spray.io spray-client for a more complete implementation of async http with scala.

    ReplyDelete
  2. the only problem with them is that you have to get this libraries on your classpath, just to use the simple async http client, which in time might end up like apache dependency hell... I've seen projects with 400+ jars just because somebody used one class from every jar...

    ReplyDelete