+doc #20699 improve docs for akka-http (#20722)

Made imports in docs snippets more complete and a few minor improvements
This commit is contained in:
Michal Sitko 2016-06-07 00:17:23 +02:00 committed by Konrad Malawski
parent 87a9196088
commit bf76d6c389
15 changed files with 197 additions and 161 deletions

View file

@ -14,7 +14,6 @@ import akka.http.javadsl.model.ws.TextMessage;
import akka.http.javadsl.model.ws.WebSocketRequest; import akka.http.javadsl.model.ws.WebSocketRequest;
import akka.http.javadsl.model.ws.WebSocketUpgradeResponse; import akka.http.javadsl.model.ws.WebSocketUpgradeResponse;
import akka.japi.Pair; import akka.japi.Pair;
import akka.japi.function.Procedure;
import akka.stream.ActorMaterializer; import akka.stream.ActorMaterializer;
import akka.stream.Materializer; import akka.stream.Materializer;
import akka.stream.javadsl.Flow; import akka.stream.javadsl.Flow;
@ -63,9 +62,9 @@ public class WebSocketClientExampleTest {
// The first value in the pair is a CompletionStage<WebSocketUpgradeResponse> that // The first value in the pair is a CompletionStage<WebSocketUpgradeResponse> that
// completes when the WebSocket request has connected successfully (or failed) // completes when the WebSocket request has connected successfully (or failed)
final CompletionStage<Done> connected = pair.first().thenApply(upgrade -> { final CompletionStage<Done> connected = pair.first().thenApply(upgrade -> {
// just like a regular http request we can get 404 NotFound, // just like a regular http request we can access response status which is available via upgrade.response.status
// with a response body, that will be available from upgrade.response // status code 101 (Switching Protocols) indicates that server support WebSockets
if (upgrade.response().status().equals(StatusCodes.OK)) { if (upgrade.response().status().equals(StatusCodes.SWITCHING_PROTOCOLS)) {
return Done.getInstance(); return Done.getInstance();
} else { } else {
throw new RuntimeException("Connection failed: " + upgrade.response().status()); throw new RuntimeException("Connection failed: " + upgrade.response().status());
@ -220,9 +219,9 @@ public class WebSocketClientExampleTest {
CompletionStage<Done> connected = upgradeCompletion.thenApply(upgrade-> CompletionStage<Done> connected = upgradeCompletion.thenApply(upgrade->
{ {
// just like a regular http request we can get 404 NotFound, // just like a regular http request we can access response status which is available via upgrade.response.status
// with a response body, that will be available from upgrade.response // status code 101 (Switching Protocols) indicates that server support WebSockets
if (upgrade.response().status().equals(StatusCodes.OK)) { if (upgrade.response().status().equals(StatusCodes.SWITCHING_PROTOCOLS)) {
return Done.getInstance(); return Done.getInstance();
} else { } else {
throw new RuntimeException(("Connection failed: " + upgrade.response().status())); throw new RuntimeException(("Connection failed: " + upgrade.response().status()));

View file

@ -119,7 +119,7 @@ If, however, your marshaller also needs to set things like the response status c
or any headers then a ``ToEntityMarshaller[T]`` won't work. You'll need to fall down to providing a or any headers then a ``ToEntityMarshaller[T]`` won't work. You'll need to fall down to providing a
``ToResponseMarshaller[T]`` or a ``ToRequestMarshaller[T]`` directly. ``ToResponseMarshaller[T]`` or a ``ToRequestMarshaller[T]`` directly.
For writing you own marshallers you won't have to "manually" implement the ``Marshaller`` trait directly. For writing your own marshallers you won't have to "manually" implement the ``Marshaller`` trait directly.
Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller`` Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller``
companion: companion:

View file

@ -77,7 +77,7 @@ Custom Unmarshallers
Akka HTTP gives you a few convenience tools for constructing unmarshallers for your own types. Akka HTTP gives you a few convenience tools for constructing unmarshallers for your own types.
Usually you won't have to "manually" implement the ``Unmarshaller`` trait directly. Usually you won't have to "manually" implement the ``Unmarshaller`` trait directly.
Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller`` Rather, it should be possible to use one of the convenience construction helpers defined on the ``Unmarshaller``
companion: companion:
TODO rewrite sample for Java TODO rewrite sample for Java

View file

@ -32,7 +32,7 @@ Bind failures
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
For example the server might be unable to bind to the given port. For example when the port For example the server might be unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``). is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the CompletionStage's completion: In this case the "binding future" will fail immediately, and we can react to if by listening on the CompletionStage's completion:
.. includecode:: ../../code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java .. includecode:: ../../code/docs/http/javadsl/server/HighLevelServerBindFailureExample.java
:include: binding-failure-high-level-example :include: binding-failure-high-level-example

View file

@ -5,36 +5,48 @@
package docs.http.scaladsl package docs.http.scaladsl
import akka.actor.{ ActorLogging, ActorSystem } import akka.actor.{ ActorLogging, ActorSystem }
import akka.stream.{ ActorMaterializerSettings }
import akka.util.ByteString import akka.util.ByteString
import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
class HttpClientExampleSpec extends WordSpec with Matchers { class HttpClientExampleSpec extends WordSpec with Matchers with CompileOnlySpec {
"outgoing-connection-example" in { "outgoing-connection-example" in compileOnlySpec {
pending // compile-time only test
//#outgoing-connection-example //#outgoing-connection-example
import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model._ import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import scala.concurrent.Future import scala.concurrent.Future
import scala.util.{ Failure, Success }
implicit val system = ActorSystem() object WebClient {
implicit val materializer = ActorMaterializer() def main(args: Array[String]): Unit = {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val executionContext = system.dispatcher
val connectionFlow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = val connectionFlow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] =
Http().outgoingConnection("akka.io") Http().outgoingConnection("akka.io")
val responseFuture: Future[HttpResponse] = val responseFuture: Future[HttpResponse] =
Source.single(HttpRequest(uri = "/")) Source.single(HttpRequest(uri = "/"))
.via(connectionFlow) .via(connectionFlow)
.runWith(Sink.head) .runWith(Sink.head)
responseFuture.andThen {
case Success(_) => println("request succeded")
case Failure(_) => println("request failed")
}.andThen {
case _ => system.terminate()
}
}
}
//#outgoing-connection-example //#outgoing-connection-example
} }
"host-level-example" in { "host-level-example" in compileOnlySpec {
pending // compile-time only test
//#host-level-example //#host-level-example
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model._ import akka.http.scaladsl.model._
@ -55,8 +67,7 @@ class HttpClientExampleSpec extends WordSpec with Matchers {
//#host-level-example //#host-level-example
} }
"single-request-example" in { "single-request-example" in compileOnlySpec {
pending // compile-time only test
//#single-request-example //#single-request-example
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model._ import akka.http.scaladsl.model._
@ -72,8 +83,7 @@ class HttpClientExampleSpec extends WordSpec with Matchers {
//#single-request-example //#single-request-example
} }
"single-request-in-actor-example" in { "single-request-in-actor-example" in compileOnlySpec {
pending // compile-time only test
//#single-request-in-actor-example //#single-request-in-actor-example
import akka.actor.Actor import akka.actor.Actor
import akka.http.scaladsl.Http import akka.http.scaladsl.Http

View file

@ -5,10 +5,6 @@
package docs.http.scaladsl package docs.http.scaladsl
import akka.event.LoggingAdapter import akka.event.LoggingAdapter
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{ Flow, Sink }
import akka.testkit.TestActors import akka.testkit.TestActors
import docs.CompileOnlySpec import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
@ -44,37 +40,50 @@ class HttpServerExampleSpec extends WordSpec with Matchers
"binding-failure-high-level-example" in compileOnlySpec { "binding-failure-high-level-example" in compileOnlySpec {
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
implicit val system = ActorSystem() import scala.concurrent.Future
implicit val materializer = ActorMaterializer()
// needed for the future onFailure in the end
implicit val executionContext = system.dispatcher
val handler = get { object WebServer {
complete("Hello world!") def main(args: Array[String]) {
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
// needed for the future onFailure in the end
implicit val executionContext = system.dispatcher
val handler = get {
complete("Hello world!")
}
// let's say the OS won't allow us to bind to 80.
val (host, port) = ("localhost", 80)
val bindingFuture: Future[ServerBinding] =
Http().bindAndHandle(handler, host, port)
bindingFuture.onFailure {
case ex: Exception =>
log.error(ex, "Failed to bind to {}:{}!", host, port)
}
}
} }
// let's say the OS won't allow us to bind to 80.
val (host, port) = ("localhost", 80)
val bindingFuture: Future[ServerBinding] =
Http().bindAndHandle(handler, host, port)
bindingFuture.onFailure {
case ex: Exception =>
log.error(ex, "Failed to bind to {}:{}!", host, port)
}
} }
// mock values: // mock values:
import akka.http.scaladsl.Http val handleConnections = {
import akka.actor.ActorSystem import akka.stream.scaladsl.Sink
val handleConnections: Sink[Http.IncomingConnection, Future[Http.ServerBinding]] =
Sink.ignore.mapMaterializedValue(_ => Future.failed(new Exception(""))) Sink.ignore.mapMaterializedValue(_ => Future.failed(new Exception("")))
}
"binding-failure-handling" in compileOnlySpec { "binding-failure-handling" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.stream.ActorMaterializer
import scala.concurrent.Future
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
// needed for the future onFailure in the end // needed for the future onFailure in the end
@ -102,11 +111,8 @@ class HttpServerExampleSpec extends WordSpec with Matchers
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.actor.ActorRef import akka.actor.ActorRef
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.ContentTypes
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import scala.io.StdIn import akka.stream.scaladsl.Flow
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
@ -132,8 +138,9 @@ class HttpServerExampleSpec extends WordSpec with Matchers
"connection-stream-failure-handling" in compileOnlySpec { "connection-stream-failure-handling" in compileOnlySpec {
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity } import akka.http.scaladsl.model._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Flow
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
@ -203,6 +210,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers
} }
"low-level-server-example" in compileOnlySpec { "low-level-server-example" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpMethods._ import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model._ import akka.http.scaladsl.model._
@ -286,7 +294,9 @@ class HttpServerExampleSpec extends WordSpec with Matchers
} }
"minimal-routing-example" in compileOnlySpec { "minimal-routing-example" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import scala.io.StdIn import scala.io.StdIn
@ -319,13 +329,14 @@ class HttpServerExampleSpec extends WordSpec with Matchers
"long-routing-example" in compileOnlySpec { "long-routing-example" in compileOnlySpec {
//#long-routing-example //#long-routing-example
import akka.actor.ActorRef import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.coding.Deflate import akka.http.scaladsl.coding.Deflate
import akka.http.scaladsl.marshalling.ToResponseMarshaller import akka.http.scaladsl.marshalling.ToResponseMarshaller
import akka.http.scaladsl.model.StatusCodes.MovedPermanently import akka.http.scaladsl.model.StatusCodes.MovedPermanently
import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller import akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller
import akka.pattern.ask import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.util.Timeout import akka.util.Timeout
// types used by the API routes // types used by the API routes
@ -427,6 +438,7 @@ class HttpServerExampleSpec extends WordSpec with Matchers
"stream random numbers" in compileOnlySpec { "stream random numbers" in compileOnlySpec {
//#stream-random-numbers //#stream-random-numbers
import akka.actor.ActorSystem
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.util.ByteString import akka.util.ByteString
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
@ -483,15 +495,15 @@ class HttpServerExampleSpec extends WordSpec with Matchers
"interact with an actor" in compileOnlySpec { "interact with an actor" in compileOnlySpec {
//#actor-interaction //#actor-interaction
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.actor.Props
import scala.concurrent.duration._
import akka.util.Timeout
import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.util.Timeout
import spray.json.DefaultJsonProtocol._ import spray.json.DefaultJsonProtocol._
import scala.concurrent.duration._
import scala.io.StdIn import scala.io.StdIn
object WebServer { object WebServer {

View file

@ -9,13 +9,12 @@ import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.util.ByteString import akka.util.ByteString
import com.typesafe.sslconfig.akka.AkkaSSLConfig import com.typesafe.sslconfig.akka.AkkaSSLConfig
import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
class HttpsExamplesSpec extends WordSpec with Matchers { class HttpsExamplesSpec extends WordSpec with Matchers with CompileOnlySpec {
"disable SNI for connection" in {
pending // compile-time only test
"disable SNI for connection" in compileOnlySpec {
val unsafeHost = "example.com" val unsafeHost = "example.com"
//#disable-sni-connection //#disable-sni-connection
implicit val system = ActorSystem() implicit val system = ActorSystem()

View file

@ -8,8 +8,6 @@ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.Directives import akka.http.scaladsl.server.Directives
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
import scala.concurrent.Future
class SprayJsonExampleSpec extends WordSpec with Matchers { class SprayJsonExampleSpec extends WordSpec with Matchers {
def compileOnlySpec(body: => Unit) = () def compileOnlySpec(body: => Unit) = ()
@ -53,6 +51,7 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
"second-spray-json-example" in compileOnlySpec { "second-spray-json-example" in compileOnlySpec {
//#second-spray-json-example //#second-spray-json-example
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.Done import akka.Done
import akka.http.scaladsl.server.Route import akka.http.scaladsl.server.Route
@ -61,6 +60,10 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._ import spray.json.DefaultJsonProtocol._
import scala.io.StdIn
import scala.concurrent.Future
object WebServer { object WebServer {
// domain model // domain model
@ -80,6 +83,8 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
// needed to run the route // needed to run the route
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
// needed for the future map/flatmap in the end
implicit val executionContext = system.dispatcher
val route: Route = val route: Route =
get { get {
@ -104,6 +109,13 @@ class SprayJsonExampleSpec extends WordSpec with Matchers {
} }
} }
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
} }
} }
//#second-spray-json-example //#second-spray-json-example

View file

@ -3,17 +3,14 @@
*/ */
package docs.http.scaladsl package docs.http.scaladsl
import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.{ Authorization, BasicHttpCredentials }
import docs.CompileOnlySpec import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
import scala.concurrent.Promise
class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnlySpec { class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnlySpec {
"singleWebSocket-request-example" in compileOnlySpec { "singleWebSocket-request-example" in compileOnlySpec {
//#single-WebSocket-request //#single-WebSocket-request
import akka.actor.ActorSystem
import akka.{ Done, NotUsed } import akka.{ Done, NotUsed }
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
@ -23,59 +20,60 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
import scala.concurrent.Future import scala.concurrent.Future
implicit val system = ActorSystem() object SingleWebSocketRequest {
implicit val materializer = ActorMaterializer() def main(args: Array[String]) = {
import system.dispatcher implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
import system.dispatcher
// print each incoming strict text message // print each incoming strict text message
val printSink: Sink[Message, Future[Done]] = val printSink: Sink[Message, Future[Done]] =
Sink.foreach { Sink.foreach {
case message: TextMessage.Strict => case message: TextMessage.Strict =>
println(message.text) println(message.text)
} }
val helloSource: Source[Message, NotUsed] = val helloSource: Source[Message, NotUsed] =
Source.single(TextMessage("hello world!")) Source.single(TextMessage("hello world!"))
// the Future[Done] is the materialized value of Sink.foreach // the Future[Done] is the materialized value of Sink.foreach
// and it is completed when the stream completes // and it is completed when the stream completes
val flow: Flow[Message, Message, Future[Done]] = val flow: Flow[Message, Message, Future[Done]] =
Flow.fromSinkAndSourceMat(printSink, helloSource)(Keep.left) Flow.fromSinkAndSourceMat(printSink, helloSource)(Keep.left)
// upgradeResponse is a Future[WebSocketUpgradeResponse] that // upgradeResponse is a Future[WebSocketUpgradeResponse] that
// completes or fails when the connection succeeds or fails // completes or fails when the connection succeeds or fails
// and closed is a Future[Done] representing the stream completion from above // and closed is a Future[Done] representing the stream completion from above
val (upgradeResponse, closed) = val (upgradeResponse, closed) =
Http().singleWebSocketRequest(WebSocketRequest("ws://echo.websocket.org"), flow) Http().singleWebSocketRequest(WebSocketRequest("ws://echo.websocket.org"), flow)
val connected = upgradeResponse.map { upgrade => val connected = upgradeResponse.map { upgrade =>
// just like a regular http request we can get 404 NotFound, // just like a regular http request we can access response status which is available via upgrade.response.status
// with a response body, that will be available from upgrade.response // status code 101 (Switching Protocols) indicates that server support WebSockets
if (upgrade.response.status == StatusCodes.OK) { if (upgrade.response.status == StatusCodes.SwitchingProtocols) {
Done Done
} else { } else {
throw new RuntimeException(s"Connection failed: ${upgrade.response.status}") throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
}
}
// in a real application you would not side effect here
// and handle errors more carefully
connected.onComplete(println)
closed.foreach(_ => println("closed"))
} }
} }
// in a real application you would not side effect here
// and handle errors more carefully
connected.onComplete(println)
closed.foreach(_ => println("closed"))
//#single-WebSocket-request //#single-WebSocket-request
} }
"half-closed-WebSocket-closing-example" in compileOnlySpec { "half-closed-WebSocket-closing-example" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.{ Done, NotUsed } import akka.{ Done, NotUsed }
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.ws._ import akka.http.scaladsl.model.ws._
import scala.concurrent.Future
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
import system.dispatcher import system.dispatcher
@ -97,14 +95,13 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
} }
"half-closed-WebSocket-working-example" in compileOnlySpec { "half-closed-WebSocket-working-example" in compileOnlySpec {
import akka.{ Done, NotUsed } import akka.actor.ActorSystem
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.ws._ import akka.http.scaladsl.model.ws._
import scala.concurrent.Future import scala.concurrent.Promise
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
@ -130,14 +127,14 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
} }
"half-closed-WebSocket-finite-working-example" in compileOnlySpec { "half-closed-WebSocket-finite-working-example" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.{ Done, NotUsed } import akka.{ Done, NotUsed }
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.ws._ import akka.http.scaladsl.model.ws._
import scala.concurrent.Future import scala.concurrent.Promise
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
@ -163,11 +160,14 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
} }
"authorized-singleWebSocket-request-example" in compileOnlySpec { "authorized-singleWebSocket-request-example" in compileOnlySpec {
import akka.actor.ActorSystem
import akka.NotUsed import akka.NotUsed
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.http.scaladsl.model.headers.{ Authorization, BasicHttpCredentials }
import akka.http.scaladsl.model.ws._ import akka.http.scaladsl.model.ws._
implicit val system = ActorSystem() implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
import collection.immutable.Seq import collection.immutable.Seq
@ -187,6 +187,7 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
"WebSocketClient-flow-example" in compileOnlySpec { "WebSocketClient-flow-example" in compileOnlySpec {
//#WebSocket-client-flow //#WebSocket-client-flow
import akka.actor.ActorSystem
import akka.Done import akka.Done
import akka.http.scaladsl.Http import akka.http.scaladsl.Http
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
@ -196,48 +197,51 @@ class WebSocketClientExampleSpec extends WordSpec with Matchers with CompileOnly
import scala.concurrent.Future import scala.concurrent.Future
implicit val system = ActorSystem() object WebSocketClientFlow {
implicit val materializer = ActorMaterializer() def main(args: Array[String]) = {
import system.dispatcher implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
import system.dispatcher
// Future[Done] is the materialized value of Sink.foreach, // Future[Done] is the materialized value of Sink.foreach,
// emitted when the stream completes // emitted when the stream completes
val incoming: Sink[Message, Future[Done]] = val incoming: Sink[Message, Future[Done]] =
Sink.foreach[Message] { Sink.foreach[Message] {
case message: TextMessage.Strict => case message: TextMessage.Strict =>
println(message.text) println(message.text)
} }
// send this as a message over the WebSocket // send this as a message over the WebSocket
val outgoing = Source.single(TextMessage("hello world!")) val outgoing = Source.single(TextMessage("hello world!"))
// flow to use (note: not re-usable!) // flow to use (note: not re-usable!)
val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("ws://echo.websocket.org")) val webSocketFlow = Http().webSocketClientFlow(WebSocketRequest("ws://echo.websocket.org"))
// the materialized value is a tuple with // the materialized value is a tuple with
// upgradeResponse is a Future[WebSocketUpgradeResponse] that // upgradeResponse is a Future[WebSocketUpgradeResponse] that
// completes or fails when the connection succeeds or fails // completes or fails when the connection succeeds or fails
// and closed is a Future[Done] with the stream completion from the incoming sink // and closed is a Future[Done] with the stream completion from the incoming sink
val (upgradeResponse, closed) = val (upgradeResponse, closed) =
outgoing outgoing
.viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse] .viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse]
.toMat(incoming)(Keep.both) // also keep the Future[Done] .toMat(incoming)(Keep.both) // also keep the Future[Done]
.run() .run()
// just like a regular http request we can get 404 NotFound etc. // just like a regular http request we can access response status which is available via upgrade.response.status
// that will be available from upgrade.response // status code 101 (Switching Protocols) indicates that server support WebSockets
val connected = upgradeResponse.flatMap { upgrade => val connected = upgradeResponse.flatMap { upgrade =>
if (upgrade.response.status == StatusCodes.OK) { if (upgrade.response.status == StatusCodes.SwitchingProtocols) {
Future.successful(Done) Future.successful(Done)
} else { } else {
throw new RuntimeException(s"Connection failed: ${upgrade.response.status}") throw new RuntimeException(s"Connection failed: ${upgrade.response.status}")
}
}
// in a real application you would not side effect here
connected.onComplete(println)
closed.foreach(_ => println("closed"))
} }
} }
// in a real application you would not side effect here
connected.onComplete(println)
closed.foreach(_ => println("closed"))
//#WebSocket-client-flow //#WebSocket-client-flow
} }

View file

@ -6,11 +6,11 @@ package docs.http.scaladsl.server
import akka.http.scaladsl.model.ws.BinaryMessage import akka.http.scaladsl.model.ws.BinaryMessage
import akka.stream.scaladsl.Sink import akka.stream.scaladsl.Sink
import docs.CompileOnlySpec
import org.scalatest.{ Matchers, WordSpec } import org.scalatest.{ Matchers, WordSpec }
class WebSocketExampleSpec extends WordSpec with Matchers { class WebSocketExampleSpec extends WordSpec with Matchers with CompileOnlySpec {
"core-example" in { "core-example" in compileOnlySpec {
pending // compile-time only test
//#websocket-example-using-core //#websocket-example-using-core
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
@ -64,8 +64,7 @@ class WebSocketExampleSpec extends WordSpec with Matchers {
.flatMap(_.unbind()) // trigger unbinding from the port .flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done .onComplete(_ => system.terminate()) // and shutdown when done
} }
"routing-example" in { "routing-example" in compileOnlySpec {
pending // compile-time only test
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.stream.ActorMaterializer import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{ Source, Flow } import akka.stream.scaladsl.{ Source, Flow }

View file

@ -55,8 +55,6 @@ class TimeoutDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec {
} }
"allow mapping the response" in compileOnlySpec { "allow mapping the response" in compileOnlySpec {
pending // compile only spec since requires actuall Http server to be run
//#withRequestTimeoutResponse //#withRequestTimeoutResponse
val timeoutResponse = HttpResponse( val timeoutResponse = HttpResponse(
StatusCodes.EnhanceYourCalm, StatusCodes.EnhanceYourCalm,

View file

@ -118,7 +118,7 @@ If, however, your marshaller also needs to set things like the response status c
or any headers then a ``ToEntityMarshaller[T]`` won't work. You'll need to fall down to providing a or any headers then a ``ToEntityMarshaller[T]`` won't work. You'll need to fall down to providing a
``ToResponseMarshaller[T]`` or a ``ToRequestMarshaller[T]`` directly. ``ToResponseMarshaller[T]`` or a ``ToRequestMarshaller[T]`` directly.
For writing you own marshallers you won't have to "manually" implement the ``Marshaller`` trait directly. For writing your own marshallers you won't have to "manually" implement the ``Marshaller`` trait directly.
Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller`` Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller``
companion: companion:

View file

@ -76,7 +76,7 @@ Custom Unmarshallers
Akka HTTP gives you a few convenience tools for constructing unmarshallers for your own types. Akka HTTP gives you a few convenience tools for constructing unmarshallers for your own types.
Usually you won't have to "manually" implement the ``Unmarshaller`` trait directly. Usually you won't have to "manually" implement the ``Unmarshaller`` trait directly.
Rather, it should be possible to use one of the convenience construction helpers defined on the ``Marshaller`` Rather, it should be possible to use one of the convenience construction helpers defined on the ``Unmarshaller``
companion: companion:
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/Unmarshaller.scala .. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/unmarshalling/Unmarshaller.scala

View file

@ -25,11 +25,14 @@ Akka HTTP was designed specifically as “not-a-framework”, not because we don
Using Akka HTTP Using Akka HTTP
--------------- ---------------
Akka HTTP is provided in separate jar files, to use it make sure to include the following dependencies:: Akka HTTP is provided in a separate jar file, to use it make sure to include the following dependency::
"com.typesafe.akka" %% "akka-http-core" % "@version@" @crossString@
"com.typesafe.akka" %% "akka-http-experimental" % "@version@" @crossString@ "com.typesafe.akka" %% "akka-http-experimental" % "@version@" @crossString@
Mind that ``akka-http`` comes in two modules: ``akka-http-experimental`` and ``akka-http-core``. Because ``akka-http-experimental``
depends on ``akka-http-core`` you don't need to bring the latter explicitly. Still you may need to this in case you rely
solely on low-level API.
Routing DSL for HTTP servers Routing DSL for HTTP servers
---------------------------- ----------------------------

View file

@ -58,7 +58,7 @@ Bind failures
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
For example the server might be unable to bind to the given port. For example when the port For example the server might be unable to bind to the given port. For example when the port
is already taken by another application, or if the port is privileged (i.e. only usable by ``root``). is already taken by another application, or if the port is privileged (i.e. only usable by ``root``).
In this case the "binding future" will fail immediatly, and we can react to if by listening on the Future's completion: In this case the "binding future" will fail immediately, and we can react to if by listening on the Future's completion:
.. includecode2:: ../../code/docs/http/scaladsl/HttpServerExampleSpec.scala .. includecode2:: ../../code/docs/http/scaladsl/HttpServerExampleSpec.scala
:snippet: binding-failure-high-level-example :snippet: binding-failure-high-level-example