Advertisement
Guest User

Untitled

a guest
Mar 18th, 2015
242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 4.16 KB | None | 0 0
  1. package com.ctilogic.cvd.common.http
  2.  
  3. import akka.actor._
  4. import akka.pattern.ask
  5. import akka.util.Timeout
  6. import com.ctilogic.cvd.common.{Hardcoded, CommonConfig}
  7. import com.ctilogic.cvd.common.api.Entity
  8. import com.github.levkhomich.akka.tracing.{TracingSupport, ActorTracing}
  9. import com.github.levkhomich.akka.tracing.http.TracingDirectives
  10. import reactivemongo.bson.BSONObjectID
  11. import spray.http._
  12. import spray.routing._
  13. import shapeless._
  14. import spray.http.HttpRequest
  15. import spray.httpx.marshalling._
  16. import spray.httpx.unmarshalling._
  17.  
  18. import scala.concurrent.{Future, ExecutionContext}
  19.  
  20. import com.ctilogic.cvd.common.messaging.{ErrorResponse}
  21. import com.ctilogic.cvd.common.marshalling.CommonMarshalling._
  22.  
  23.  
  24. /**
  25.  * This trait provide helpers for HTTP routing and processing requests by cluster services.
  26.  * It should be implemented by all services which requires REST processing by cluster services.
  27.  *
  28.  * See examples:
  29.  * {{{
  30.  * trait VersionSprayService { this: CommonSprayService =>
  31.  *   registerRoute{
  32.  *     path("version") {
  33.  *       get {
  34.  *         complete(HttpResponse(StatusCodes.OK, "0.0.1"))
  35.  *       }
  36.  *     }
  37.  *   }
  38.  * }
  39.  * }}}
  40.  *
  41.  * {{{
  42.  * trait ACLSprayService { this : CommonSprayService ⇒
  43.  *   private val SessionsPath = "sessions"
  44.  *
  45.  *   registerApiRoute(
  46.  *     path(SessionsPath) {
  47.  *       post {
  48.  *         tracedHandleRest[CreateSessionRequest, CreateSessionResponse]
  49.  *       }
  50.  *     } ~
  51.  *     (path(SessionsPath / EntityId) & delete) { EntityId ⇒
  52.  *       tracedHandleRest[DeleteSessionRequest, SuccessResponse]
  53.  *     } ~
  54.  *     // ... cut
  55.  *   }
  56.  * }
  57.  * }}}
  58.  *
  59.  * Final implementation HTTP listener with SprayServices.
  60.  * {{{
  61.  *   class MySprayHTTPListener extends BaseSprayService with VersionSprayService with ACLSprayService
  62.  * }}}
  63.  */
  64. trait CommonSprayService extends HttpService with RouteRegistration with CommonPaths with ActorTracing with TracingDirectives
  65. {
  66.     type RestResult[T] = Future[Either[ErrorResponse, T]]
  67.  
  68.   implicit protected def requestTimeout: Timeout
  69.     implicit protected val executionContext: ExecutionContext
  70.  
  71.     /**
  72.      * Request processor actor. All requests routed to this actor by call [[restProcess]].
  73.      */
  74.     protected val requestProcessor: ActorRef
  75.  
  76.  
  77.     /**
  78.      * Process rest request by `requestProcessor`
  79.      * @param request request.
  80.      * @tparam A type of request
  81.      * @tparam B type of response
  82.      * @return future with response or error.
  83.      */
  84.     protected def restProcess[A, B](request: A): RestResult[B] = {
  85.         (requestProcessor ? request).mapTo[Either[ErrorResponse, B]]
  86.     }
  87.  
  88.  
  89.     // TODO: FIXME tracing support
  90.     /**
  91.      * Handle request using [[restProcess]] with tracing.
  92.      * @param um request unmarshaller
  93.      * @param m response marshaller
  94.      * @tparam A request type
  95.      * @tparam B response type
  96.      * @return spray route which handle the request
  97.      */
  98.     def tracedHandleRest[A <: TracingSupport, B](implicit um: FromRequestUnmarshaller[A],   m:  ToResponseMarshaller[B])
  99.     : Route = tracedHandleWith(restProcess[A, B])
  100.  
  101.     def tracedHandleWith[A <: TracingSupport, B, G <: HList](extracted: G)(f: A ⇒ B)
  102.             (implicit um: Deserializer[HttpRequest :: G, A], m: ToResponseMarshaller[B], ma: Manifest[A]): Route = {
  103.         implicit val umm = wrap(extracted)
  104.         tracedHandleWith(f)
  105.     }
  106.  
  107.     private def wrap[A, G <: HList](extracted: G)(implicit um: Deserializer[HttpRequest :: G, A]): FromRequestUnmarshaller[A] =
  108.         new Deserializer[HttpRequest, A] {
  109.             override def apply(httpRequest: HttpRequest): Deserialized[A] = {
  110.                 um(::(httpRequest, extracted))
  111.             }
  112.         }
  113.  
  114.     protected val offsetLimit = parameters('offset.as[Int].?, 'limit.as[Int].?)
  115.  
  116.     val BSONObjectIDSegment: PathMatcher1[BSONObjectID] =
  117.         PathMatcher("""[\da-fA-F]{24}""".r).map(BSONObjectID.apply)
  118.  
  119.     val UUIDStringSegment: PathMatcher1[String] =
  120.         PathMatcher("""[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}""".r)
  121.  
  122.     /**
  123.      * Register API router.
  124.      *
  125.      * Alias for
  126.      * {{{
  127.      * registerRoute {
  128.      *   path("/api") {
  129.      *     route
  130.      *   }
  131.      * }
  132.      * }}}
  133.      *
  134.      * @param route
  135.      */
  136.     protected def registerApiRoute(route: Route) : Unit = registerRoute {
  137.         pathPrefix(ApiPath) {
  138.             route
  139.         }
  140.     }
  141. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement