Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.ctilogic.cvd.common.http
- import akka.actor._
- import akka.pattern.ask
- import akka.util.Timeout
- import com.ctilogic.cvd.common.{Hardcoded, CommonConfig}
- import com.ctilogic.cvd.common.api.Entity
- import com.github.levkhomich.akka.tracing.{TracingSupport, ActorTracing}
- import com.github.levkhomich.akka.tracing.http.TracingDirectives
- import reactivemongo.bson.BSONObjectID
- import spray.http._
- import spray.routing._
- import shapeless._
- import spray.http.HttpRequest
- import spray.httpx.marshalling._
- import spray.httpx.unmarshalling._
- import scala.concurrent.{Future, ExecutionContext}
- import com.ctilogic.cvd.common.messaging.{ErrorResponse}
- import com.ctilogic.cvd.common.marshalling.CommonMarshalling._
- /**
- * This trait provide helpers for HTTP routing and processing requests by cluster services.
- * It should be implemented by all services which requires REST processing by cluster services.
- *
- * See examples:
- * {{{
- * trait VersionSprayService { this: CommonSprayService =>
- * registerRoute{
- * path("version") {
- * get {
- * complete(HttpResponse(StatusCodes.OK, "0.0.1"))
- * }
- * }
- * }
- * }
- * }}}
- *
- * {{{
- * trait ACLSprayService { this : CommonSprayService ⇒
- * private val SessionsPath = "sessions"
- *
- * registerApiRoute(
- * path(SessionsPath) {
- * post {
- * tracedHandleRest[CreateSessionRequest, CreateSessionResponse]
- * }
- * } ~
- * (path(SessionsPath / EntityId) & delete) { EntityId ⇒
- * tracedHandleRest[DeleteSessionRequest, SuccessResponse]
- * } ~
- * // ... cut
- * }
- * }
- * }}}
- *
- * Final implementation HTTP listener with SprayServices.
- * {{{
- * class MySprayHTTPListener extends BaseSprayService with VersionSprayService with ACLSprayService
- * }}}
- */
- trait CommonSprayService extends HttpService with RouteRegistration with CommonPaths with ActorTracing with TracingDirectives
- {
- type RestResult[T] = Future[Either[ErrorResponse, T]]
- implicit protected def requestTimeout: Timeout
- implicit protected val executionContext: ExecutionContext
- /**
- * Request processor actor. All requests routed to this actor by call [[restProcess]].
- */
- protected val requestProcessor: ActorRef
- /**
- * Process rest request by `requestProcessor`
- * @param request request.
- * @tparam A type of request
- * @tparam B type of response
- * @return future with response or error.
- */
- protected def restProcess[A, B](request: A): RestResult[B] = {
- (requestProcessor ? request).mapTo[Either[ErrorResponse, B]]
- }
- // TODO: FIXME tracing support
- /**
- * Handle request using [[restProcess]] with tracing.
- * @param um request unmarshaller
- * @param m response marshaller
- * @tparam A request type
- * @tparam B response type
- * @return spray route which handle the request
- */
- def tracedHandleRest[A <: TracingSupport, B](implicit um: FromRequestUnmarshaller[A], m: ToResponseMarshaller[B])
- : Route = tracedHandleWith(restProcess[A, B])
- def tracedHandleWith[A <: TracingSupport, B, G <: HList](extracted: G)(f: A ⇒ B)
- (implicit um: Deserializer[HttpRequest :: G, A], m: ToResponseMarshaller[B], ma: Manifest[A]): Route = {
- implicit val umm = wrap(extracted)
- tracedHandleWith(f)
- }
- private def wrap[A, G <: HList](extracted: G)(implicit um: Deserializer[HttpRequest :: G, A]): FromRequestUnmarshaller[A] =
- new Deserializer[HttpRequest, A] {
- override def apply(httpRequest: HttpRequest): Deserialized[A] = {
- um(::(httpRequest, extracted))
- }
- }
- protected val offsetLimit = parameters('offset.as[Int].?, 'limit.as[Int].?)
- val BSONObjectIDSegment: PathMatcher1[BSONObjectID] =
- PathMatcher("""[\da-fA-F]{24}""".r).map(BSONObjectID.apply)
- val UUIDStringSegment: PathMatcher1[String] =
- PathMatcher("""[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}""".r)
- /**
- * Register API router.
- *
- * Alias for
- * {{{
- * registerRoute {
- * path("/api") {
- * route
- * }
- * }
- * }}}
- *
- * @param route
- */
- protected def registerApiRoute(route: Route) : Unit = registerRoute {
- pathPrefix(ApiPath) {
- route
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement