=doc #19840 Introduction docs for HTTP
This commit is contained in:
parent
06b4d54960
commit
61ff9ba9b9
5 changed files with 382 additions and 67 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
package docs.http.scaladsl
|
||||
|
||||
import akka.actor.{ ActorRef, ActorSystem }
|
||||
import akka.actor.{ Props, ActorRef, ActorSystem }
|
||||
import akka.event.LoggingAdapter
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.Http.ServerBinding
|
||||
|
|
@ -13,6 +13,7 @@ import akka.stream.ActorMaterializer
|
|||
import akka.stream.scaladsl.{ Flow, Sink }
|
||||
import akka.testkit.TestActors
|
||||
import org.scalatest.{ Matchers, WordSpec }
|
||||
import scala.io.StdIn
|
||||
import scala.language.postfixOps
|
||||
|
||||
import scala.concurrent.{ ExecutionContext, Future }
|
||||
|
|
@ -31,7 +32,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val serverSource: Source[Http.IncomingConnection, Future[Http.ServerBinding]] =
|
||||
Http().bind(interface = "localhost", port = 8080)
|
||||
|
|
@ -49,7 +50,8 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
// needed for the future onFailure in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val handler = get {
|
||||
complete("Hello world!")
|
||||
|
|
@ -60,7 +62,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
val bindingFuture: Future[ServerBinding] =
|
||||
Http().bindAndHandle(handler, host, port)
|
||||
|
||||
bindingFuture onFailure {
|
||||
bindingFuture.onFailure {
|
||||
case ex: Exception =>
|
||||
log.error(ex, "Failed to bind to {}:{}!", host, port)
|
||||
}
|
||||
|
|
@ -74,7 +76,8 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
"binding-failure-handling" in compileOnlySpec {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
// needed for the future onFailure in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
// let's say the OS won't allow us to bind to 80.
|
||||
val (host, port) = ("localhost", 80)
|
||||
|
|
@ -84,7 +87,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
.to(handleConnections) // Sink[Http.IncomingConnection, _]
|
||||
.run()
|
||||
|
||||
bindingFuture onFailure {
|
||||
bindingFuture.onFailure {
|
||||
case ex: Exception =>
|
||||
log.error(ex, "Failed to bind to {}:{}!", host, port)
|
||||
}
|
||||
|
|
@ -97,7 +100,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
"incoming-connections-source-failure-handling" in compileOnlySpec {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
import Http._
|
||||
val (host, port) = ("localhost", 8080)
|
||||
|
|
@ -119,7 +122,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
"connection-stream-failure-handling" in compileOnlySpec {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val (host, port) = ("localhost", 8080)
|
||||
val serverSource = Http().bind(host, port)
|
||||
|
|
@ -153,6 +156,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val serverSource = Http().bind(interface = "localhost", port = 8080)
|
||||
|
||||
|
|
@ -186,87 +190,110 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
import akka.http.scaladsl.model.HttpMethods._
|
||||
import akka.http.scaladsl.model._
|
||||
import akka.stream.ActorMaterializer
|
||||
import scala.io.StdIn
|
||||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
object WebServer {
|
||||
|
||||
val requestHandler: HttpRequest => HttpResponse = {
|
||||
case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
|
||||
HttpResponse(entity = HttpEntity(ContentTypes.`text/html(UTF-8)`,
|
||||
"<html><body>Hello world!</body></html>"))
|
||||
def main(args: Array[String]) {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
// needed for the future map/flatmap in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
case HttpRequest(GET, Uri.Path("/ping"), _, _, _) =>
|
||||
HttpResponse(entity = "PONG!")
|
||||
val requestHandler: HttpRequest => HttpResponse = {
|
||||
case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
|
||||
HttpResponse(entity = HttpEntity(ContentTypes.`text/html(UTF-8)`,
|
||||
"<html><body>Hello world!</body></html>"))
|
||||
|
||||
case HttpRequest(GET, Uri.Path("/crash"), _, _, _) =>
|
||||
sys.error("BOOM!")
|
||||
case HttpRequest(GET, Uri.Path("/ping"), _, _, _) =>
|
||||
HttpResponse(entity = "PONG!")
|
||||
|
||||
case _: HttpRequest =>
|
||||
HttpResponse(404, entity = "Unknown resource!")
|
||||
case HttpRequest(GET, Uri.Path("/crash"), _, _, _) =>
|
||||
sys.error("BOOM!")
|
||||
|
||||
case _: HttpRequest =>
|
||||
HttpResponse(404, entity = "Unknown resource!")
|
||||
}
|
||||
|
||||
val bindingFuture = Http().bindAndHandleSync(requestHandler, "localhost", 8080)
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
bindingFuture
|
||||
.flatMap(_.unbind()) // trigger unbinding from the port
|
||||
.onComplete(_ ⇒ system.terminate()) // and shutdown when done
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Http().bindAndHandleSync(requestHandler, "localhost", 8080)
|
||||
}
|
||||
|
||||
// format: OFF
|
||||
|
||||
"high-level-server-example" in compileOnlySpec {
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.stream.ActorMaterializer
|
||||
import scala.io.StdIn
|
||||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
object WebServer {
|
||||
def main(args: Array[String]) {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
// needed for the future flatMap/onComplete in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val route =
|
||||
get {
|
||||
pathSingleSlash {
|
||||
complete {
|
||||
<html>
|
||||
<body>Hello world!</body>
|
||||
</html>
|
||||
val route =
|
||||
get {
|
||||
pathSingleSlash {
|
||||
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))
|
||||
} ~
|
||||
path("ping") {
|
||||
complete("PONG!")
|
||||
} ~
|
||||
path("crash") {
|
||||
sys.error("BOOM!")
|
||||
}
|
||||
}
|
||||
} ~
|
||||
path("ping") {
|
||||
complete("PONG!")
|
||||
} ~
|
||||
path("crash") {
|
||||
sys.error("BOOM!")
|
||||
}
|
||||
}
|
||||
|
||||
// `route` will be implicitly converted to `Flow` using `RouteResult.route2HandlerFlow`
|
||||
Http().bindAndHandle(route, "localhost", 8080)
|
||||
// `route` will be implicitly converted to `Flow` using `RouteResult.route2HandlerFlow`
|
||||
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
bindingFuture
|
||||
.flatMap(_.unbind()) // trigger unbinding from the port
|
||||
.onComplete(_ ⇒ system.terminate()) // and shutdown when done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"minimal-routing-example" in compileOnlySpec {
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.stream.ActorMaterializer
|
||||
import scala.io.StdIn
|
||||
|
||||
object Main extends App {
|
||||
implicit val system = ActorSystem("my-system")
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val ec = system.dispatcher
|
||||
object WebServer {
|
||||
def main(args: Array[String]) {
|
||||
|
||||
val route =
|
||||
path("hello") {
|
||||
get {
|
||||
complete {
|
||||
<h1>Say hello to akka-http</h1>
|
||||
implicit val system = ActorSystem("my-system")
|
||||
implicit val materializer = ActorMaterializer()
|
||||
// needed for the future flatMap/onComplete in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val route =
|
||||
path("hello") {
|
||||
get {
|
||||
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
|
||||
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.terminate()) // and shutdown when done
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
bindingFuture
|
||||
.flatMap(_.unbind()) // trigger unbinding from the port
|
||||
.onComplete(_ ⇒ system.terminate()) // and shutdown when done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,4 +407,121 @@ class HttpServerExampleSpec extends WordSpec with Matchers {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
"stream random numbers" in compileOnlySpec {
|
||||
//#stream-random-numbers
|
||||
import akka.stream.scaladsl._
|
||||
import akka.util.ByteString
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.model.{HttpEntity, ContentTypes}
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.stream.ActorMaterializer
|
||||
import scala.util.Random
|
||||
import scala.io.StdIn
|
||||
|
||||
object WebServer {
|
||||
|
||||
def main(args: Array[String]) {
|
||||
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
// needed for the future flatMap/onComplete in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
// streams are re-usable so we can define it here
|
||||
// and use it for every request
|
||||
val numbers = Source.fromIterator(() =>
|
||||
Iterator.continually(Random.nextInt()))
|
||||
|
||||
val route =
|
||||
path("random") {
|
||||
get {
|
||||
complete(
|
||||
HttpEntity(
|
||||
ContentTypes.`text/plain(UTF-8)`,
|
||||
// transform each number to a chunk of bytes
|
||||
numbers.map(n => ByteString(s"$n\n"))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
bindingFuture
|
||||
.flatMap(_.unbind()) // trigger unbinding from the port
|
||||
.onComplete(_ ⇒ system.terminate()) // and shutdown when done
|
||||
}
|
||||
}
|
||||
//#stream-random-numbers
|
||||
}
|
||||
|
||||
|
||||
object Auction {
|
||||
def props: Props = ???
|
||||
}
|
||||
|
||||
"interact with an actor" in compileOnlySpec {
|
||||
//#actor-interaction
|
||||
import scala.concurrent.duration._
|
||||
import akka.util.Timeout
|
||||
import akka.pattern.ask
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
|
||||
import spray.json.DefaultJsonProtocol._
|
||||
import scala.io.StdIn
|
||||
|
||||
object WebServer {
|
||||
|
||||
case class Bid(userId: String, bid: Int)
|
||||
case object GetBids
|
||||
case class Bids(bids: List[Bid])
|
||||
|
||||
// these are from spray-json
|
||||
implicit val bidFormat = jsonFormat2(Bid)
|
||||
implicit val bidsFormat = jsonFormat1(Bids)
|
||||
|
||||
def main(args: Array[String]) {
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
// needed for the future flatMap/onComplete in the end
|
||||
implicit val executionContext = system.dispatcher
|
||||
|
||||
val auction = system.actorOf(Auction.props, "auction")
|
||||
|
||||
val route =
|
||||
path("auction") {
|
||||
put {
|
||||
parameter("bid".as[Int], "user") { (bid, user) =>
|
||||
// place a bid, fire-and-forget
|
||||
auction ! Bid(user, bid)
|
||||
complete(StatusCodes.Accepted, "bid placed")
|
||||
}
|
||||
}
|
||||
get {
|
||||
implicit val timeout: Timeout = 5.seconds
|
||||
|
||||
// query the actor for the current auction state
|
||||
val bids: Future[Bids] = (auction ? GetBids).mapTo[Bids]
|
||||
complete(bids)
|
||||
}
|
||||
}
|
||||
|
||||
val bindingFuture = Http().bindAndHandle(route, "localhost", 8080)
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
StdIn.readLine() // let it run until user presses return
|
||||
bindingFuture
|
||||
.flatMap(_.unbind()) // trigger unbinding from the port
|
||||
.onComplete(_ ⇒ system.terminate()) // and shutdown when done
|
||||
|
||||
}
|
||||
}
|
||||
//#actor-interaction
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,13 @@ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
|
|||
import akka.http.scaladsl.server.Directives
|
||||
import org.scalatest.{ Matchers, WordSpec }
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
class SprayJsonExampleSpec extends WordSpec with Matchers {
|
||||
|
||||
"spray-json example" in {
|
||||
def compileOnlySpec(body: => Unit) = ()
|
||||
|
||||
"spray-json example" in compileOnlySpec {
|
||||
//#example
|
||||
import spray.json._
|
||||
|
||||
|
|
@ -31,9 +35,7 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
|
|||
val route =
|
||||
get {
|
||||
pathSingleSlash {
|
||||
complete {
|
||||
Item("thing", 42) // will render as JSON
|
||||
}
|
||||
complete(Item("thing", 42)) // will render as JSON
|
||||
}
|
||||
} ~
|
||||
post {
|
||||
|
|
@ -47,4 +49,63 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
|
|||
//#
|
||||
}
|
||||
}
|
||||
|
||||
"second-spray-json-example" in compileOnlySpec {
|
||||
//#second-spray-json-example
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.Done
|
||||
import akka.http.scaladsl.server.Route
|
||||
import akka.http.scaladsl.server.Directives._
|
||||
import akka.http.scaladsl.model.StatusCodes
|
||||
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
|
||||
import spray.json.DefaultJsonProtocol._
|
||||
|
||||
object WebServer {
|
||||
|
||||
// domain model
|
||||
final case class Item(name: String, id: Long)
|
||||
final case class Order(items: List[Item])
|
||||
|
||||
// formats for unmarshalling and marshalling
|
||||
implicit val itemFormat = jsonFormat2(Item)
|
||||
implicit val orderFormat = jsonFormat1(Order)
|
||||
|
||||
// (fake) async database query api
|
||||
def fetchItem(itemId: Long): Future[Option[Item]] = ???
|
||||
def saveOrder(order: Order): Future[Done] = ???
|
||||
|
||||
def main(args: Array[String]) {
|
||||
|
||||
// needed to run the route
|
||||
implicit val system = ActorSystem()
|
||||
implicit val materializer = ActorMaterializer()
|
||||
|
||||
val route: Route =
|
||||
get {
|
||||
pathPrefix("item" / LongNumber) { id =>
|
||||
// there might be no item for a given id
|
||||
val maybeItem: Future[Option[Item]] = fetchItem(id)
|
||||
|
||||
onSuccess(maybeItem) {
|
||||
case Some(item) => complete(item)
|
||||
case None => complete(StatusCodes.NotFound)
|
||||
}
|
||||
}
|
||||
} ~
|
||||
post {
|
||||
path("create-order") {
|
||||
entity(as[Order]) { order =>
|
||||
val saved: Future[Done] = saveOrder(order)
|
||||
onComplete(saved) { done =>
|
||||
complete("order created")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//#second-spray-json-example
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
.. _akka-http-spray-json:
|
||||
|
||||
JSON Support
|
||||
============
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
.. _akka-http-xml-marshalling:
|
||||
|
||||
XML Support
|
||||
===========
|
||||
|
||||
|
|
|
|||
|
|
@ -10,23 +10,129 @@ You get to pick the API level of abstraction that is most suitable for your appl
|
|||
This means that, if you have trouble achieving something using a high-level API, there's a good chance that you can get
|
||||
it done with a low-level API, which offers more flexibility but might require you to write more application code.
|
||||
|
||||
Akka HTTP is structured into several modules:
|
||||
Using Akka HTTP
|
||||
---------------
|
||||
Akka HTTP is provided in separate jar files, to use it make sure to include the following dependencies::
|
||||
|
||||
akka-http-core
|
||||
A complete, mostly low-level, server- and client-side implementation of HTTP (incl. WebSockets)
|
||||
"com.typesafe.akka" %% "akka-http-core" % "@version@" @crossString@
|
||||
"com.typesafe.akka" %% "akka-http-experimental" % "@version@" @crossString@
|
||||
|
||||
|
||||
Routing DSL for HTTP servers
|
||||
----------------------------
|
||||
The high-level, routing API of Akka HTTP provides a DSL to describe HTTP "routes" and how they should be handled.
|
||||
Each route is composed of one or more level of ``Directive`` s that narrows down to handling one specific type of
|
||||
request.
|
||||
|
||||
For example one route might start with matching the ``path`` of the request, only matching if it is "/hello", then
|
||||
narrowing it down to only handle HTTP ``get`` requests and then ``complete`` those with a string literal, which
|
||||
will be sent back as a HTTP OK with the string as response body.
|
||||
|
||||
Transforming request and response bodies between over-the-wire formats and objects to be used in your application is
|
||||
done separately from the route declarations, in marshallers, which are pulled in implicitly using the "magnet" pattern.
|
||||
This means that you can ``complete`` a request with any kind of object a as long as there is an implicit marshaller
|
||||
available in scope.
|
||||
|
||||
Default marshallers are provided for simple objects like String or ByteString, and you can define your own for example
|
||||
for JSON. An additional module provides JSON serialization using the spray-json library (see :ref:`akka-http-spray-json`
|
||||
for details).
|
||||
|
||||
The ``Route`` created using the Route DSL is then "bound" to a port to start serving HTTP requests:
|
||||
|
||||
.. includecode2:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
|
||||
:snippet: minimal-routing-example
|
||||
|
||||
A common use case is to reply to a request using a model object having the marshaller transform it into JSON. In
|
||||
this case shown by two separate routes. The first route queries an asynchronous database and marshalls the
|
||||
``Future[Option[Item]]`` result into a JSON response. The second unmarshalls an ``Order`` from the incoming request
|
||||
saves it to the database and replies with an OK when done.
|
||||
|
||||
.. includecode2:: ../code/docs/http/scaladsl/SprayJsonExampleSpec.scala
|
||||
:snippet: second-spray-json-example
|
||||
|
||||
The logic for the marshalling and unmarshalling JSON in this example is provided by the "spray-json" library
|
||||
(details on how to use that here: :ref:`akka-http-spray-json`).
|
||||
|
||||
One of the strengths of Akka HTTP is that streaming data is at its heart meaning that both request and response bodies
|
||||
can be streamed through the server achieving constant memory usage even for very large requests or responses. Streaming
|
||||
responses will be backpressured by the remote client so that the server will not push data faster than the client can
|
||||
handle, streaming requests means that the server decides how fast the remote client can push the data of the request
|
||||
body.
|
||||
|
||||
Example that streams random numbers as long as the client accepts them:
|
||||
|
||||
.. includecode:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
|
||||
:include: stream-random-numbers
|
||||
|
||||
Connecting to this service with a slow HTTP client would backpressure so that the next random number is produced on
|
||||
demand with constant memory usage on the server. This can be seen using curl and limiting the rate
|
||||
``curl --limit-rate 50b 127.0.0.1:8080/random``
|
||||
|
||||
|
||||
Akka HTTP routes easily interacts with actors. In this example one route allows for placing bids in a fire-and-forget
|
||||
style while the second route contains a request-response interaction with an actor. The resulting response is rendered
|
||||
as json and returned when the response arrives from the actor.
|
||||
|
||||
.. includecode:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
|
||||
:include: actor-interaction
|
||||
|
||||
Again the logic for the marshalling and unmarshalling JSON in this example is provided by the "spray-json" library
|
||||
(details on how to use that here: :ref:`akka-http-spray-json`)
|
||||
|
||||
|
||||
Read more about the details of the high level APIs in the section :ref:`http-high-level-server-side-api`.
|
||||
|
||||
Low-level HTTP server APIs
|
||||
--------------------------
|
||||
The low-level Akka HTTP server APIs allows for handling connections or individual requests by accepting
|
||||
``HttpRequest`` s and answering them by producing ``HttpResponse`` s. This is provided by the ``akka-http-core`` module.
|
||||
APIs for handling such request-responses as function calls and as a ``Flow[HttpRequest, HttpResponse, _]`` are available.
|
||||
|
||||
.. includecode2:: ../code/docs/http/scaladsl/HttpServerExampleSpec.scala
|
||||
:snippet: low-level-server-example
|
||||
|
||||
Read more details about the low level APIs in the section :ref:`http-low-level-server-side-api`.
|
||||
|
||||
|
||||
HTTP client API
|
||||
---------------
|
||||
The client APIs provide methods for calling a HTTP server using the same ``HttpRequest`` and ``HttpResponse`` abstractions
|
||||
that Akka HTTP server uses but adds the concept of connection pools to allow multiple requests to the same server to be
|
||||
handled more performantly by re-using TCP connections to the server.
|
||||
|
||||
Example simple request:
|
||||
|
||||
.. includecode:: ../code/docs/http/scaladsl/HttpClientExampleSpec.scala
|
||||
:include: single-request-example
|
||||
|
||||
|
||||
Read more about the details of the client APIs in the section :ref:`http-client-side`.
|
||||
|
||||
|
||||
|
||||
The modules that make up Akka HTTP
|
||||
----------------------------------
|
||||
Akka HTTP is structured into several modules:
|
||||
|
||||
akka-http
|
||||
Higher-level functionality, like (un)marshalling, (de)compression as well as a powerful DSL
|
||||
for defining HTTP-based APIs on the server-side
|
||||
for defining HTTP-based APIs on the server-side, this is the recommended way to write HTTP servers
|
||||
with Akka HTTP. Details can be found in the section :ref:`http-high-level-server-side-api`
|
||||
|
||||
akka-http-core
|
||||
A complete, mostly low-level, server- and client-side implementation of HTTP (incl. WebSockets)
|
||||
Details can be found in sections :ref:`http-low-level-server-side-api` and :ref:`http-client-side`
|
||||
|
||||
akka-http-testkit
|
||||
A test harness and set of utilities for verifying server-side service implementations
|
||||
|
||||
akka-http-spray-json
|
||||
Predefined glue-code for (de)serializing custom types from/to JSON with spray-json_
|
||||
Details can be found here: :ref:`akka-http-spray-json`
|
||||
|
||||
akka-http-xml
|
||||
Predefined glue-code for (de)serializing custom types from/to XML with scala-xml_
|
||||
Details can be found here: :ref:`akka-http-xml-marshalling`
|
||||
|
||||
.. _spray-json: https://github.com/spray/spray-json
|
||||
.. _scala-xml: https://github.com/scala/scala-xml
|
||||
Loading…
Add table
Add a link
Reference in a new issue