Spray(12)spray-can - Http Client HttpDialog and Spray Client

Spray(12)spray-can-HttpClientHttpDialogandSprayClient

3.HttpClient

HttpsExample

ThedifferencebetweenHttpandHttpsforHttpDialogisthat,whattagswebringtoit.

valresponseFuture=

HttpDialog(httpClient,"github.com",port=443,HttpClient.SslEnabled)

.send(HttpRequest(uri="/spray/spray"))

.end

GoogleQueryExample

Checkalltheconfigurationinspray-can/src/main/resources/reference.conf

WhatIneedtoforthespray-canisasfollow:

spray.can{

client{

idle-timeout=60s

request-timeout=30s

}

server{

request-timeout=50s

}

}

Wecandotherequestsinqueue.

4.HttpDialog

packagecom.sillycat.easyspray.httpdialog

importjava.util.concurrent.TimeUnit._

importscala.concurrent.Future

importscala.concurrent.duration.Duration

importspray.can.client.{HttpDialog,HttpClient}

importspray.io._

importspray.http._

importHttpMethods._

importakka.actor.ActorSystem

importakka.actor.Props

importspray.httpx.RequestBuilding._

objectSimpleExampleAppextendsApp{

implicitvalsystem=ActorSystem("simple-example")

importsystem.log

//differentwaytogetthehttpClientobject

valioBridge=IOExtension(system).ioBridge()

valclient=system.actorOf(Props(newHttpClient(ioBridge)))

//simplerequest

valresponse:Future[HttpResponse]=

HttpDialog(client,"www.google.com",80)

.send(HttpRequest(method=GET,uri="/"))

.end

//multiplerequests,fireonebyone

valresponses1:Future[Seq[HttpResponse]]=

HttpDialog(client,"www.google.com",80)

.send(Post("/shout","yeah!"))

.awaitResponse

.send(Put("/count","42"))

.end

//multiplerequests,fireatsametime

valresponses2:Future[Seq[HttpResponse]]=

HttpDialog(client,"www.google.com",80)

.send(Get("/img/a.gif"))

.send(Get("/img/b.gif"))

.send(Get("/img/c.gif"))

.end

//multiplerequests,firefollowthisrequest->response->request

valresponse3:Future[HttpResponse]=

HttpDialog(client,"www.google.com",80)

.send(Get("/ping"))

.reply(response=>Get("/ping2",response.entity))

.end

}

5.SprayClient

Thedefaultconfigurationfilewillbespray-client/src/main/resources/reference.conf

MyfirstSimplestExample

packagecom.sillycat.easyspray.sprayclient

importspray.client._

importscala.concurrent.Future

importakka.actor._

importspray.can.client.HttpClient

importspray.client.HttpConduit

importspray.io._

importspray.util._

importspray.http._

importHttpMethods._

importscala.util.{Success,Failure}

importscala.concurrent.duration._

importakka.actor.{Props,ActorSystem}

importakka.pattern.ask

importakka.util.Timeout

importakka.event.Logging

importspray.json.{JsonFormat,DefaultJsonProtocol}

importspray.httpx.SprayJsonSupport

importspray.http._

importspray.util._

objectSprayClientAppextendsApp{

implicitvalsystem=ActorSystem()

valioBridge=IOExtension(system).ioBridge()

valhttpClient=system.actorOf(Props(newHttpClient(ioBridge)))

valconduit=system.actorOf(

props=Props(newHttpConduit(httpClient,"maps.googleapis.com",80)),

name="http-conduit")

valpipeline=HttpConduit.sendReceive(conduit)

valresponse:Future[HttpResponse]=pipeline(HttpRequest(method=GET,uri="/maps/api/elevation/json?locations=27.988056,86.925278&sensor=false"))

responseonComplete{

caseSuccess(responseContent)=>

println("TheelevationofMt.Everestis:{}m"+responseContent)

shutdown()

caseFailure(error)=>

println("Couldn'tgetelevation")

shutdown()

}

defshutdown():Unit={

system.shutdown()

}

}

Let'stakealookatthetheExamplefromofficialwebsite

Firstofall,thejsonMarshallthings.

packagecom.sillycat.easyspray.sprayclient.version11m7

importspray.json.{JsonFormat,DefaultJsonProtocol}

caseclassElevation(location:Location,elevation:Double)

caseclassLocation(lat:Double,lng:Double)

caseclassGoogleApiResult[T](status:String,results:List[T])

objectElevationJsonProtocolextendsDefaultJsonProtocol{

implicitvallocationFormat=jsonFormat2(Location)

implicitvalelevationFormat=jsonFormat2(Elevation)

implicitdefgoogleApiResultFormat[T:JsonFormat]=jsonFormat2(GoogleApiResult.apply[T])

}

Hereisthemainpart.

packagecom.sillycat.easyspray.sprayclient.version11m7

importscala.util.{Success,Failure}

importakka.actor.{Props,ActorSystem}

importspray.can.client.DefaultHttpClient

importspray.client.HttpConduit

importspray.httpx.SprayJsonSupport

importspray.http._

importspray.util._

objectMainextendsApp{

//weneedanActorSystemtohostourapplicationin

implicitvalsystem=ActorSystem("simple-spray-client")

importsystem.log

//createandstartthedefaultspray-canHttpClient

valhttpClient=DefaultHttpClient(system)

startExample1()

defstartExample1(){

log.info("Gettinghttp://github.com...")

//anHttpConduitgivesusaccesstoanHTTPserver,

//itmanagesapoolofconnectionsto_one_host/portcombination

//GetaConduit

valconduit=system.actorOf(

props=Props(newHttpConduit(httpClient,"github.com")),

name="http-conduit-1"

)

//sendasimplerequest

valpipeline=HttpConduit.sendReceive(conduit)

valresponseFuture=pipeline(HttpRequest(method=HttpMethods.GET,uri="/"))

responseFutureonComplete{

caseSuccess(response)=>

log.info(

"""|ResponseforGETrequesttogithub.com:

|status:{}

|headers:{}

|body:{}""".stripMargin,

response.status.value,response.headers.mkString("\n","\n",""),response.entity.asString

)

system.stop(conduit)//theconduitcanbestoppedwhenalloperationsonithavebeencompleted

startExample2()

caseFailure(error)=>

log.error(error,"Couldn'tgethttp://github.com")

system.shutdown()//alsostopsallconduits(sincetheyareactors)

}

}

//BuildtheSecondconduit

defstartExample2(){

log.info("RequestingtheelevationofMt.EverestfromGooglesElevationAPI...")

valconduit=system.actorOf(

props=Props(newHttpConduit(httpClient,"maps.googleapis.com")),

name="http-conduit-2"

)

importHttpConduit._

importElevationJsonProtocol._

importSprayJsonSupport._

//sendtherequestandunmarshal

valpipeline=sendReceive(conduit)~>unmarshal[GoogleApiResult[Elevation]]

valresponseF=pipeline(Get("/maps/api/elevation/json?locations=27.988056,86.925278&sensor=false"))

responseFonComplete{

caseSuccess(response)=>

log.info("TheelevationofMt.Everestis:{}m",response.results.head.elevation)

system.shutdown()//alsostopsallconduits(sincetheyareactors)

caseFailure(error)=>

log.error(error,"Couldn'tgetelevation")

system.shutdown()//alsostopsallconduits(sincetheyareactors)

}

}

}

SomeothermagicNotintheExample

caseclassOrder(id:Int)

caseclassOrderConfirmation(id:Int)

objectMyJsonProtocolextendsDefaultJsonProtocol{

implicitvalorderFormat=jsonFormat1(Order)

implicitvalorderConfirmationFormat=jsonFormat1(OrderConfirmation)

}

importHttpConduit._

importMyJsonProtocol._

valpipeline:HttpRequest=>Future[OrderConfirmation]=(

addHeader("X-My-Special-Header","fancy-value")

~>addCredentials(BasicHttpCredentials("bob","secret"))

~>encode(Gzip)

~>sendReceive(conduit)

~>decode(Deflate)

~>unmarshal[OrderConfirmation]

)

valconfirmation:Future[OrderConfirmation]=

pipeline(Post("/orders",Order(42))

Tillnow,Igoteverythingfromthedocument.Iplantointegratethatintheproject.

Tips:

References:

spray(12)spray-can-HttpClient

HttpDialog

http://spray.io/documentation/spray-can/http-dialog/