How to stop a DSL routed Spray server without upgrading to Akka HTTP?

I have this route:

val route = pathPrefix("es") {
  path("se") {
    post {
      entity(as[JsValue]) {
        t =>
          complete("ok")
      }
    }
  } ~ path("q" / "show") {
    get {
      complete(q)
    }
  }
}

When I try to bind it to stop it (according to https://doc.akka.io/docs/akka-http/current/routing-dsl/index.html ), I get a compilation error:

val bindingFuture = Http().bindAndHandle(route, "0.0.0.0", 9100)

Error: (54, 46) type mismatch; found: spray.routing.Route (which expands to) spray.routing.RequestContext => Required device: akka.stream.scaladsl.Flow [akka.http.scaladsl.model.HttpRequest, akka.http.scaladsl.model.HttpResponse, any] val bindingFuture = Http (). bindAndHandle (route, "0.0.0.0", 9100)

How to stop the HTTP server? Currently, I can start the HTTP server using:

startServer("0.0.0.0", port)

However, I do not see how to stop it with a function startServer.

UPDATE: Spray Akka HTTP, (, ).

Http().bindAndHandle, akka-http-core_2.11-2.4.11.1.jar. , RouteResult Flow. RouteResult akka-http-core_2.11-2.4.11.1.jar.

+4
3

, Spray Akka HTTP. , . Akka HTTP, Spray, HTTP- Akka Spray:

, Http.Unbind HttpListener (ActorRef Http.Bound ).

Http.Unbound ( Http.CommandFailed ). .

-, SimpleRoutingApp, startServer. HttpListener. , Http.Unbind , .

, , HttpListener:

import akka.actor._
import spray.can.Http
import spray.routing._

object MyActor {
  case object GetListener
  def props(route: => Route): Props = Props(new MyActor(route))
}

class MyActor(route: => Route) extends HttpServiceActor {
  import MyActor._

  var httpListener: Option[ActorRef] = None

  def routeReceive: Receive = runRoute(route)

  def serverLifecycleReceive: Receive = {
    case b: Http.Bound =>
      println(s"Successfully bound to ${b.localAddress}")
      val listener = sender()
      httpListener = Some(listener)
    case GetListener =>
      httpListener.foreach(sender ! _)
  }

  def receive = routeReceive orElse serverLifecycleReceive
}

SimpleRoutingApp, :

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.Success
import akka.actor._
import akka.io.IO
import akka.pattern.ask
import akka.util.Timeout
import spray.can.Http
import spray.http._
import spray.routing._
import MyActor

object Main extends App {

  implicit val system = ActorSystem()
  import system.dispatcher
  implicit val timeout = Timeout(5.seconds)

  val route = ???

  val handler = system.actorOf(MyActor.props(route), name = "handler")

  IO(Http) ! Http.Bind(handler, interface = "0.0.0.0", port = 9100)

  // run the below code to shut down the server before shutting down the actor system
  (handler ? MyActor.GetListener)
    .flatMap { case actor: ActorRef => (actor ? Http.Unbind) }
    .onComplete {
      case Success(u: Http.Unbound) =>
        println("Unbinding from the port is done.")
        // system.shutdown()
      case _ =>
        println("Unbinding failed.")
    }
}

, ( ) . , , , . , , ( Spray)

object Main extends App with SimpleRoutingApp {
  implicit val system = ActorSystem("simple-routing-app")
  import system.dispatcher

  val route = ...
    ~ (post | parameter('method ! "post")) {
      path("stop") {
        complete {
          system.scheduler.scheduleOnce(1.second)(system.shutdown())(system.dispatcher)
          "Shutting down in 1 second..."
        }
      }
    }

  startServer("0.0.0.0", port = 9100) {
    route
  }.onComplete {
    case Success(b) =>
      println(s"Successfully bound to ${b.localAddress}")
    case Failure(ex) =>
      println(ex.getMessage)
      system.shutdown()
  }
}
+6

Akka HTTP Spray. Spray Akka, , ( :

val route = ???

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
+2

, , spray.routing.Route. Spray Akka HTTP Route. , Akka HTTP .

Secondly, you will need and implicit ActorMaterializer(s ActorSystem) in scope to be able to implicitly convert your Routeto Flow[akka.http.scaladsl.model.HttpRequest,akka.http.scaladsl.model.HttpResponse,Any]which the method expects bindAndHandle.

+1
source

Source: https://habr.com/ru/post/1692581/


All Articles