38
AKKA HTTP A.K.A. SPRAY 2.0 Présenté par Jean Detoeuf / @thebignet

Akka http 2

Embed Size (px)

Citation preview

Page 1: Akka http 2

AKKA HTTPA.K.A. SPRAY 2.0

Présenté par Jean Detoeuf / @thebignet

Page 2: Akka http 2

JEAN DETOEUFDÉVELOPPEUR

Passionné de nouvelles technologies

#jvm #docker #craftmanship #rpi #diy

Page 3: Akka http 2

AVERTISSEMENTJe ne suis pas un expert en Scala

Soyez sympas ^^

Page 4: Akka http 2

PROJET EN COURS DE MATURATIONversion lors de cette présentation2.0.1

mélange entre Spray et AkkaJ'ai eu l'idée de cette présentation à la version 1.0, il était temps !

Page 5: Akka http 2

AKKA STREAMSPrésenté au SLUG par en février 2015Frédéric Masion

Source ~> Flow ~> Sink

Source décrit une source de données

Flow représente une transformation de ces données

Sink une opération terminale

Page 6: Akka http 2

AKKA STREAMSSource ~> Flow1 ~> Flow2a ~> Sink

~> Flow2b

Fan-out / Fan-in

Page 7: Akka http 2

AKKA HTTPConstuit sur Akka Streams

Internet est un tuyaurempli de chatons

Page 8: Akka http 2

AKKA HTTP

Flow[HttpRequest, HttpResponse]

Page 9: Akka http 2

AKKA HTTPClient et serveur

Mettre des acteurs sur HTTP

Page 10: Akka http 2

MODULESakka-http-spray-json

akka-http-xml

akka-http-testkit

akka-http

akka-http-core

Page 11: Akka http 2

C'EST BON, MONTRE-MOI LE CODELes exemples sont pour la plupart tirés de la documentation

d'Akka

Page 12: Akka http 2

EXEMPLE SIMPLE

import akka.http.scaladsl.Http import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer object Main extends App { implicit val system = ActorSystem("my-system") implicit val materializer = ActorMaterializer() implicit val ec = system.dispatcher val route = path("hello") { get { complete { <h1>Say hello to akka-http</h1> } } } val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") Console.readLine() // for the future transformations bindingFuture .flatMap(_.unbind()) // trigger unbinding from the port .onComplete(_ ⇒ system.shutdown()) // and shutdown when done }

Page 13: Akka http 2

EXEMPLE SIMPLE

import akka.http.scaladsl.Http import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer object Main extends App { implicit val system = ActorSystem("my-system") implicit val materializer = ActorMaterializer() implicit val ec = system.dispatcher val route = path("hello") { get { complete { <h1>Say hello to akka-http</h1> } } } val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") Console.readLine() // for the future transformations bindingFuture .flatMap(_.unbind()) // trigger unbinding from the port .onComplete(_ ⇒ system.shutdown()) // and shutdown when done }

Page 14: Akka http 2

EXEMPLE SIMPLE

import akka.http.scaladsl.Http import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer object Main extends App { implicit val system = ActorSystem("my-system") implicit val materializer = ActorMaterializer() implicit val ec = system.dispatcher val route = path("hello") { get { complete { <h1>Say hello to akka-http</h1> } } } val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") Console.readLine() // for the future transformations bindingFuture .flatMap(_.unbind()) // trigger unbinding from the port .onComplete(_ ⇒ system.shutdown()) // and shutdown when done }

Page 15: Akka http 2

EXEMPLE SIMPLE

import akka.http.scaladsl.Http import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer object Main extends App { implicit val system = ActorSystem("my-system") implicit val materializer = ActorMaterializer() implicit val ec = system.dispatcher val route = path("hello") { get { complete { <h1>Say hello to akka-http</h1> } } } val bindingFuture = Http().bindAndHandle(route, "localhost", 8080) println(s"Server online at http://localhost:8080/\nPress RETURN to stop...") Console.readLine() // for the future transformations bindingFuture .flatMap(_.unbind()) // trigger unbinding from the port .onComplete(_ ⇒ system.shutdown()) // and shutdown when done }

Page 16: Akka http 2

MARSHALLING/UNMARSHALLING

Page 17: Akka http 2

MARSHALLING/UNMARSHALLINGComment passer d'un flux HTTP à Scala et inversement ?

Page 18: Akka http 2

MARSHALLINGMarshallers prédéfinis

Array[Byte] ByteString Array[Char] String akka.http.scaladsl.model.FormData akka.http.scaladsl.model.MessageEntity T <: akka.http.scaladsl.model.Multipart T si ToEntityMarshaller[T] est présent

Page 19: Akka http 2

MARSHALLINGRésolution implicite

Si le type ToEntityMarshaller[T] est défini, il est utilisé

Page 20: Akka http 2

UNMARSHALLINGUnmarshallers prédéfinis

Byte Short Int Long Float Double Boolean Array[Byte] ByteString Array[Char] String akka.http.scaladsl.model.FormData

Page 21: Akka http 2

ROUTAGE

Page 22: Akka http 2

LOW-LEVELimport akka.http.scaladsl.Http import akka.http.scaladsl.model.HttpMethods._ import akka.http.scaladsl.model._ import akka.stream.ActorMaterializer implicit val system = ActorSystem() implicit val materializer = ActorMaterializer() val requestHandler: HttpRequest => HttpResponse = { case HttpRequest(GET, Uri.Path("/"), _, _, _) => HttpResponse(entity = HttpEntity(ContentTypes.text/html(UTF-8), "Hello world!")) case HttpRequest(GET, Uri.Path("/ping"), _, _, _) => HttpResponse(entity = "PONG!") case HttpRequest(GET, Uri.Path("/crash"), _, _, _) => sys.error("BOOM!") case _: HttpRequest => HttpResponse(404, entity = "Unknown resource!") } Http().bindAndHandleSync(requestHandler, "localhost", 8080)

Page 23: Akka http 2

HIGH-LEVELimport akka.http.scaladsl.Http import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ import akka.http.scaladsl.server.Directives._ import akka.stream.ActorMaterializer implicit val system = ActorSystem() implicit val materializer = ActorMaterializer() val route = get { pathSingleSlash { complete { <html> <body>Hello world!</body> </html> } } ~ path("ping") { complete("PONG!") } ~ path("crash") { sys.error("BOOM!") } } // route will be implicitly converted to Flow using RouteResult

Page 24: Akka http 2

// route will be implicitly converted to Flow using RouteResult.route2HandlerFlow Http().bindAndHandle(route, "localhost", 8080)

Page 25: Akka http 2

DIRECTIVES

Page 26: Akka http 2

DIRECTIVESIntercepte la requête

Filtrage de la requête

Transformation de la requête ou réponse

Extraire des informations

Page 27: Akka http 2

EXEMPLEval route = path("order" / IntNumber) { id => (get | put) { extractMethod { m => complete(s"Received ${m.name} request for order $id") } } }

Page 28: Akka http 2

EXEMPLE 2val orderGetOrPutWithMethod = path("order" / IntNumber) & (get | put) & extractMethod val route = orderGetOrPutWithMethod { (id, m) => complete(s"Received ${m.name} request for order $id") }

Page 29: Akka http 2

et

PATHMATCHERval matcher: PathMatcher1[Option[Int]] = "foo" / "bar" / "X" ~ IntNumber.? / ("edit" | "create")

Intercepte les chemins suivants :foo/bar/X42/edit

foo/bar/X/create

Page 30: Akka http 2

EXTRACTION CASE CLASScase class Color(red: Int, green: Int, blue: Int) val route = path("color") { parameters('red.as[Int], 'green.as[Int], 'blue.as[Int]).as(Color) { color => // utiliser color } }

Page 31: Akka http 2

VALIDATION CASE CLASScase class Color(name: String, red: Int, green: Int, blue: Int) { require(!name.isEmpty, "color name must not be empty") require(0 <= red && red <= 255, "red color component must be between 0 and 255") require(0 <= green && green <= 255, "green color component must be between 0 and 255") require(0 <= blue && blue <= 255, "blue color component must be between 0 and 255") }

ValidationRejection si require ne passe pas

Par défaut : 400 Bad Request

Page 32: Akka http 2

TESTS

Page 33: Akka http 2

Pour la route suivanteval smallRoute = get { pathSingleSlash { complete { "Hello World !" } } ~ path("ping") { complete("PONG !") } }

Test"Hello World ! non renvoyé sur /" in { Get() ~> smallRoute ~> check { status === StatusCodes.OK responseAs[String] shouldEqual "Hello World !" } }

Page 34: Akka http 2

Pour la même route ...val smallRoute = get { pathSingleSlash { complete { "Hello World !" } } ~ path("ping") { complete("PONG !") } }

Test"GET sur chemin inconnu non pris en compte" in { Get("/pouet") ~> smallRoute ~> check { handled shouldBe false } }

Page 35: Akka http 2

VARIABLES UTILISABLES DANS LESTESTS

entityAs

handled

header

response

status

entre autres ...

Page 36: Akka http 2

CLIENTval responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = "http://akka.io"))

Page 37: Akka http 2

QUESTIONS ?

Page 38: Akka http 2

MERCI POUR VOTRE ÉCOUTE

Cette présentation :

@thebignetthebignetthebignet

talk-akka-http