!htp remove ScalaRoutingDSL
This commit is contained in:
parent
ddb007c52f
commit
80f125f481
10 changed files with 88 additions and 130 deletions
|
|
@ -15,7 +15,7 @@ import akka.http.server._
|
|||
import akka.http.model._
|
||||
import StatusCodes._
|
||||
import HttpMethods._
|
||||
import ScalaRoutingDSL._
|
||||
import Directives._
|
||||
|
||||
class ScalatestRouteTestSpec extends FreeSpec with Matchers with ScalatestRouteTest {
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ package akka.http.server
|
|||
import akka.http.model
|
||||
import model.HttpMethods._
|
||||
import model.StatusCodes
|
||||
import akka.http.server.PathMatchers.{ Segment, IntNumber }
|
||||
|
||||
class BasicRouteSpecs extends RoutingSpec {
|
||||
|
||||
|
|
@ -40,7 +39,6 @@ class BasicRouteSpecs extends RoutingSpec {
|
|||
val stringDirective = provide("The cat")
|
||||
val intDirective = provide(42)
|
||||
val doubleDirective = provide(23.0)
|
||||
val symbolDirective = provide('abc)
|
||||
|
||||
val dirStringInt = stringDirective & intDirective
|
||||
val dirStringIntDouble = dirStringInt & doubleDirective
|
||||
|
|
@ -78,7 +76,7 @@ class BasicRouteSpecs extends RoutingSpec {
|
|||
}
|
||||
"Route disjunction" should {
|
||||
"work in the happy case" in {
|
||||
val route = sealRoute((path("abc") | path("def")) {
|
||||
val route = Route.seal((path("abc") | path("def")) {
|
||||
completeOk
|
||||
})
|
||||
|
||||
|
|
@ -138,7 +136,7 @@ class BasicRouteSpecs extends RoutingSpec {
|
|||
case object MyException extends RuntimeException
|
||||
"Route sealing" should {
|
||||
"catch route execution exceptions" in {
|
||||
Get("/abc") ~> ScalaRoutingDSL.sealRoute {
|
||||
Get("/abc") ~> Route.seal {
|
||||
get { ctx ⇒
|
||||
throw MyException
|
||||
}
|
||||
|
|
@ -147,7 +145,7 @@ class BasicRouteSpecs extends RoutingSpec {
|
|||
}
|
||||
}
|
||||
"catch route building exceptions" in {
|
||||
Get("/abc") ~> ScalaRoutingDSL.sealRoute {
|
||||
Get("/abc") ~> Route.seal {
|
||||
get {
|
||||
throw MyException
|
||||
}
|
||||
|
|
@ -157,7 +155,7 @@ class BasicRouteSpecs extends RoutingSpec {
|
|||
}
|
||||
"convert all rejections to responses" in {
|
||||
object MyRejection extends Rejection
|
||||
Get("/abc") ~> ScalaRoutingDSL.sealRoute {
|
||||
Get("/abc") ~> Route.seal {
|
||||
get {
|
||||
reject(MyRejection)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import org.scalatest.{ WordSpec, Suite, Matchers }
|
|||
import akka.http.model.HttpResponse
|
||||
import akka.http.testkit.ScalatestRouteTest
|
||||
|
||||
trait GenericRoutingSpec extends Matchers with ScalaRoutingDSL with ScalatestRouteTest { this: Suite ⇒
|
||||
trait GenericRoutingSpec extends Matchers with Directives with ScalatestRouteTest { this: Suite ⇒
|
||||
val Ok = HttpResponse()
|
||||
val completeOk = complete(Ok)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,9 @@ package akka.http.server
|
|||
import akka.http.marshallers.xml.ScalaXmlSupport
|
||||
import akka.http.server.directives.AuthenticationDirectives._
|
||||
import com.typesafe.config.{ ConfigFactory, Config }
|
||||
import scala.concurrent.duration._
|
||||
import akka.actor.ActorSystem
|
||||
import akka.stream.FlowMaterializer
|
||||
import akka.util.Timeout
|
||||
import akka.http.Http
|
||||
import akka.http.model._
|
||||
|
||||
object TestServer extends App {
|
||||
val testConf: Config = ConfigFactory.parseString("""
|
||||
|
|
@ -22,8 +19,8 @@ object TestServer extends App {
|
|||
import system.dispatcher
|
||||
implicit val materializer = FlowMaterializer()
|
||||
|
||||
import ScalaRoutingDSL._
|
||||
import ScalaXmlSupport._
|
||||
import Directives._
|
||||
|
||||
def auth =
|
||||
HttpBasicAuthenticator.provideUserName {
|
||||
|
|
@ -33,25 +30,24 @@ object TestServer extends App {
|
|||
|
||||
val binding = Http().bind(interface = "localhost", port = 8080)
|
||||
|
||||
val materializedMap =
|
||||
handleConnections(binding) withRoute {
|
||||
get {
|
||||
path("") {
|
||||
complete(index)
|
||||
} ~
|
||||
path("secure") {
|
||||
HttpBasicAuthentication("My very secure site")(auth) { user ⇒
|
||||
complete(<html><body>Hello <b>{ user }</b>. Access has been granted!</body></html>)
|
||||
}
|
||||
} ~
|
||||
path("ping") {
|
||||
complete("PONG!")
|
||||
} ~
|
||||
path("crash") {
|
||||
complete(sys.error("BOOM!"))
|
||||
val materializedMap = binding startHandlingWith {
|
||||
get {
|
||||
path("") {
|
||||
complete(index)
|
||||
} ~
|
||||
path("secure") {
|
||||
HttpBasicAuthentication("My very secure site")(auth) { user ⇒
|
||||
complete(<html><body>Hello <b>{ user }</b>. Access has been granted!</body></html>)
|
||||
}
|
||||
}
|
||||
} ~
|
||||
path("ping") {
|
||||
complete("PONG!")
|
||||
} ~
|
||||
path("crash") {
|
||||
complete(sys.error("BOOM!"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println(s"Server online at http://localhost:8080/\nPress RETURN to stop...")
|
||||
Console.readLine()
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class AuthenticationDirectivesSpec extends RoutingSpec {
|
|||
} ~> check { rejection shouldEqual AuthenticationFailedRejection(CredentialsRejected, challenge) }
|
||||
}
|
||||
"reject requests with illegal Authorization header with 401" in {
|
||||
Get() ~> RawHeader("Authorization", "bob alice") ~> sealRoute {
|
||||
Get() ~> RawHeader("Authorization", "bob alice") ~> Route.seal {
|
||||
dontAuth { echoComplete }
|
||||
} ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
|
|
@ -52,7 +52,7 @@ class AuthenticationDirectivesSpec extends RoutingSpec {
|
|||
"properly handle exceptions thrown in its inner route" in {
|
||||
object TestException extends RuntimeException
|
||||
Get() ~> Authorization(BasicHttpCredentials("Alice", "")) ~> {
|
||||
sealRoute {
|
||||
Route.seal {
|
||||
doAuth { _ ⇒ throw TestException }
|
||||
}
|
||||
} ~> check { status shouldEqual StatusCodes.InternalServerError }
|
||||
|
|
@ -66,7 +66,7 @@ class AuthenticationDirectivesSpec extends RoutingSpec {
|
|||
}
|
||||
val bothAuth = dontAuth | otherAuth
|
||||
|
||||
Get() ~> sealRoute {
|
||||
Get() ~> Route.seal {
|
||||
bothAuth { echoComplete }
|
||||
} ~> check {
|
||||
status shouldEqual StatusCodes.Unauthorized
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class RangeDirectivesSpec extends RoutingSpec with Inspectors with Inside {
|
|||
}
|
||||
|
||||
"be transparent to non-200 responses" in {
|
||||
Get() ~> addHeader(Range(ByteRange(1, 2))) ~> sealRoute(wrs(reject())) ~> check {
|
||||
Get() ~> addHeader(Range(ByteRange(1, 2))) ~> Route.seal(wrs(reject())) ~> check {
|
||||
status == NotFound
|
||||
headers.exists { case `Content-Range`(_, _) ⇒ true; case _ ⇒ false } shouldEqual false
|
||||
}
|
||||
|
|
|
|||
56
akka-http/src/main/scala/akka/http/server/Route.scala
Normal file
56
akka-http/src/main/scala/akka/http/server/Route.scala
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.http.server
|
||||
|
||||
import scala.concurrent.Future
|
||||
import akka.stream.scaladsl.Flow
|
||||
import akka.http.model.{ HttpRequest, HttpResponse }
|
||||
import akka.http.util.FastFuture._
|
||||
|
||||
object Route {
|
||||
|
||||
/**
|
||||
* Helper for constructing a Route from a function literal.
|
||||
*/
|
||||
def apply(f: Route): Route = f
|
||||
|
||||
/**
|
||||
* "Seals" a route by wrapping it with exception handling and rejection conversion.
|
||||
*/
|
||||
def seal(route: Route)(implicit setup: RoutingSetup): Route = {
|
||||
import directives.ExecutionDirectives._
|
||||
import setup._
|
||||
val sealedExceptionHandler =
|
||||
if (exceptionHandler.isDefault) exceptionHandler
|
||||
else exceptionHandler orElse ExceptionHandler.default(settings)
|
||||
val sealedRejectionHandler =
|
||||
if (rejectionHandler.isDefault) rejectionHandler
|
||||
else rejectionHandler orElse RejectionHandler.default
|
||||
handleExceptions(sealedExceptionHandler) {
|
||||
handleRejections(sealedRejectionHandler) {
|
||||
route
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a `Route` into an server flow.
|
||||
*/
|
||||
def handlerFlow(route: Route)(implicit setup: RoutingSetup): Flow[HttpRequest, HttpResponse] =
|
||||
Flow[HttpRequest].mapAsync(asyncHandler(route))
|
||||
|
||||
/**
|
||||
* Turns a `Route` into an async handler function.
|
||||
*/
|
||||
def asyncHandler(route: Route)(implicit setup: RoutingSetup): HttpRequest ⇒ Future[HttpResponse] = {
|
||||
import setup._
|
||||
val sealedRoute = seal(route)
|
||||
request ⇒
|
||||
sealedRoute(new RequestContextImpl(request, routingLog.requestLog(request), setup.settings)).fast.map {
|
||||
case RouteResult.Complete(response) ⇒ response
|
||||
case RouteResult.Rejected(rejected) ⇒ throw new IllegalStateException(s"Unhandled rejections '$rejected', unsealed RejectionHandler?!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
package akka.http.server
|
||||
|
||||
import scala.collection.immutable
|
||||
|
||||
import akka.http.model.HttpResponse
|
||||
import akka.stream.scaladsl.Flow
|
||||
import akka.http.model.{ HttpRequest, HttpResponse }
|
||||
|
||||
/**
|
||||
* The result of handling a request.
|
||||
|
|
@ -19,4 +19,7 @@ sealed trait RouteResult
|
|||
object RouteResult {
|
||||
final case class Complete(response: HttpResponse) extends RouteResult
|
||||
final case class Rejected(rejections: immutable.Seq[Rejection]) extends RouteResult
|
||||
|
||||
implicit def route2HandlerFlow(route: Route)(implicit setup: RoutingSetup): Flow[HttpRequest, HttpResponse] =
|
||||
Route.handlerFlow(route)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package akka.http.server
|
||||
|
||||
import scala.concurrent.{ ExecutionContext, Future }
|
||||
import akka.stream.scaladsl._
|
||||
import akka.stream.FlowMaterializer
|
||||
import akka.http.util.FastFuture
|
||||
import akka.http.model.{ HttpRequest, HttpResponse }
|
||||
import akka.http.Http
|
||||
import FastFuture._
|
||||
|
||||
/**
|
||||
* The main entry point into the Scala routing DSL.
|
||||
*
|
||||
* `import ScalaRoutingDSL._` to bring everything required into scope.
|
||||
*/
|
||||
trait ScalaRoutingDSL extends Directives {
|
||||
|
||||
/**
|
||||
* Handles all connections from the given binding at maximum rate.
|
||||
*/
|
||||
def handleConnections(httpServerBinding: Http.ServerBinding)(implicit fm: FlowMaterializer,
|
||||
setupProvider: RoutingSetupProvider): Applicator =
|
||||
handleConnections(httpServerBinding.connections)
|
||||
|
||||
/**
|
||||
* Handles all connections from the given source at maximum rate.
|
||||
*/
|
||||
def handleConnections(connections: Source[Http.IncomingConnection])(implicit fm: FlowMaterializer,
|
||||
setupProvider: RoutingSetupProvider): Applicator =
|
||||
new Applicator {
|
||||
def withRoute(route: Route) =
|
||||
run(routeRunner(route, _))
|
||||
|
||||
def withSyncHandler(handler: HttpRequest ⇒ HttpResponse) =
|
||||
withAsyncHandler(request ⇒ FastFuture.successful(handler(request)))
|
||||
|
||||
def withAsyncHandler(handler: HttpRequest ⇒ Future[HttpResponse]) =
|
||||
run(_ ⇒ handler)
|
||||
|
||||
def run(f: RoutingSetup ⇒ HttpRequest ⇒ Future[HttpResponse]): MaterializedMap = {
|
||||
val sink = ForeachSink[Http.IncomingConnection] { connection ⇒
|
||||
val setup = setupProvider(connection)
|
||||
setup.routingLog.log.debug("Accepted new connection from " + connection.remoteAddress)
|
||||
val runner = f(setup)
|
||||
connection.handleWith(Flow[HttpRequest] mapAsync runner)
|
||||
}
|
||||
connections.to(sink).run()
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait Applicator {
|
||||
def withRoute(route: Route): MaterializedMap
|
||||
def withSyncHandler(handler: HttpRequest ⇒ HttpResponse): MaterializedMap
|
||||
def withAsyncHandler(handler: HttpRequest ⇒ Future[HttpResponse]): MaterializedMap
|
||||
}
|
||||
|
||||
def routeRunner(route: Route, setup: RoutingSetup): HttpRequest ⇒ Future[HttpResponse] = {
|
||||
import setup._
|
||||
val sealedRoute = sealRoute(route)(setup)
|
||||
request ⇒
|
||||
sealedRoute(new RequestContextImpl(request, routingLog.requestLog(request), setup.settings)).fast.map {
|
||||
case RouteResult.Complete(response) ⇒ response
|
||||
case RouteResult.Rejected(rejected) ⇒ throw new IllegalStateException(s"Unhandled rejections '$rejected', unsealed RejectionHandler?!")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Seals" a route by wrapping it with exception handling and rejection conversion.
|
||||
*/
|
||||
def sealRoute(route: Route)(implicit setup: RoutingSetup): Route = {
|
||||
import setup._
|
||||
val sealedExceptionHandler =
|
||||
if (exceptionHandler.isDefault) exceptionHandler
|
||||
else exceptionHandler orElse ExceptionHandler.default(settings)
|
||||
val sealedRejectionHandler =
|
||||
if (rejectionHandler.isDefault) rejectionHandler
|
||||
else rejectionHandler orElse RejectionHandler.default
|
||||
handleExceptions(sealedExceptionHandler) {
|
||||
handleRejections(sealedRejectionHandler) {
|
||||
route
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ScalaRoutingDSL extends ScalaRoutingDSL
|
||||
|
|
@ -15,10 +15,5 @@ package object server {
|
|||
type PathMatcher0 = PathMatcher[Unit]
|
||||
type PathMatcher1[T] = PathMatcher[Tuple1[T]]
|
||||
|
||||
/**
|
||||
* Helper for constructing a Route from a function literal.
|
||||
*/
|
||||
def Route(f: Route): Route = f
|
||||
|
||||
def FIXME = throw new RuntimeException("Not yet implemented")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue