httpp 2013-06-05
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/