akka.http.scaladsl.server.Route Scala Examples

The following examples show how to use akka.http.scaladsl.server.Route. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: AbstractWebServer.scala    From ohara   with Apache License 2.0 6 votes vote down vote up
package oharastream.ohara.shabondi.common

import akka.Done
import akka.actor.ActorSystem
import akka.event.Logging
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.server.{Directives, Route}
import akka.http.scaladsl.settings.ServerSettings
import oharastream.ohara.common.util.Releasable

import scala.concurrent._
import scala.concurrent.duration.Duration
import scala.io.StdIn
import scala.util.{Failure, Success}


private[shabondi] abstract class AbstractWebServer extends Directives with Releasable {
  implicit protected val actorSystem: ActorSystem = ActorSystem(Logging.simpleName(this).replaceAll("\\$", ""))

  protected def routes: Route

  protected def postBinding(binding: ServerBinding): Unit = {
    val hostname = binding.localAddress.getHostName
    val port     = binding.localAddress.getPort
    actorSystem.log.info(s"Server online at http://$hostname:$port/")
  }

  protected def postBindingFailure(cause: Throwable): Unit = {
    actorSystem.log.error(cause, s"Error starting the server ${cause.getMessage}")
  }

  protected def waitForShutdownSignal()(implicit ec: ExecutionContext): Future[Done] = {
    val promise = Promise[Done]()
    sys.addShutdownHook {
      promise.trySuccess(Done)
    }
    Future {
      blocking {
        if (StdIn.readLine("Press <RETURN> to stop Shabondi WebServer...\n") != null)
          promise.trySuccess(Done)
      }
    }
    promise.future
  }

  protected def postServerShutdown(): Unit = actorSystem.log.info("Shutting down the server")

  def start(bindInterface: String, port: Int): Unit = {
    start(bindInterface, port, ServerSettings(actorSystem))
  }

  def start(bindInterface: String, port: Int, settings: ServerSettings): Unit = {
    implicit val executionContext: ExecutionContextExecutor = actorSystem.dispatcher

    val bindingFuture: Future[Http.ServerBinding] = Http().bindAndHandle(
      handler = routes,
      interface = bindInterface,
      port = port,
      settings = settings
    )

    bindingFuture.onComplete {
      case Success(binding) =>
        postBinding(binding)
      case Failure(cause) =>
        postBindingFailure(cause)
    }

    Await.ready(
      bindingFuture.flatMap(_ => waitForShutdownSignal()),
      Duration.Inf
    )

    bindingFuture
      .flatMap(_.unbind())
      .onComplete { _ =>
        postServerShutdown()
        actorSystem.terminate()
      }
  }

  override def close(): Unit = actorSystem.terminate()
} 
Example 2
Source File: SinkRouteHandler.scala    From ohara   with Apache License 2.0 5 votes vote down vote up
package oharastream.ohara.shabondi.sink

import java.time.{Duration => JDuration}
import java.util.concurrent.TimeUnit

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import akka.http.scaladsl.server.{ExceptionHandler, Route}
import com.typesafe.scalalogging.Logger
import oharastream.ohara.common.data.Row
import oharastream.ohara.common.util.Releasable
import oharastream.ohara.shabondi.common.{JsonSupport, RouteHandler, ShabondiUtils}
import org.apache.commons.lang3.StringUtils

import scala.collection.mutable.ArrayBuffer
import scala.compat.java8.DurationConverters._
import scala.concurrent.ExecutionContextExecutor
import scala.concurrent.duration.Duration
import spray.json.DefaultJsonProtocol._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._

private[shabondi] object SinkRouteHandler {
  def apply(config: SinkConfig)(implicit actorSystem: ActorSystem) =
    new SinkRouteHandler(config)
}

private[shabondi] class SinkRouteHandler(config: SinkConfig)(implicit actorSystem: ActorSystem) extends RouteHandler {
  implicit private val contextExecutor: ExecutionContextExecutor = actorSystem.dispatcher

  private val log              = Logger(classOf[SinkRouteHandler])
  private[sink] val dataGroups = SinkDataGroups(config)

  def scheduleFreeIdleGroups(interval: JDuration, idleTime: JDuration): Unit =
    actorSystem.scheduler.scheduleWithFixedDelay(Duration(1, TimeUnit.SECONDS), interval.toScala) { () =>
      {
        log.trace("scheduled free group, total group: {} ", dataGroups.size)
        dataGroups.freeIdleGroup(idleTime)
      }
    }

  private val exceptionHandler = ExceptionHandler {
    case ex: Throwable =>
      log.error(ex.getMessage, ex)
      complete((StatusCodes.InternalServerError, ex.getMessage))
  }

  private def fullyPollQueue(queue: RowQueue): Seq[Row] = {
    val buffer    = ArrayBuffer.empty[Row]
    var item: Row = queue.poll()
    while (item != null) {
      buffer += item
      item = queue.poll()
    }
    buffer.toSeq
  }

  private def apiUrl = ShabondiUtils.apiUrl

  def route(): Route = handleExceptions(exceptionHandler) {
    path("groups" / Segment) { groupId =>
      get {
        if (StringUtils.isAlphanumeric(groupId)) {
          val group  = dataGroups.createIfAbsent(groupId)
          val result = fullyPollQueue(group.queue).map(row => JsonSupport.toRowData(row))
          complete(result)
        } else {
          val entity =
            HttpEntity(ContentTypes.`text/plain(UTF-8)`, "Illegal group name, only accept alpha and numeric.")
          complete(StatusCodes.NotAcceptable -> entity)
        }
      } ~ {
        complete(StatusCodes.MethodNotAllowed -> s"Unsupported method, please reference: $apiUrl")
      }
    } ~ {
      complete(StatusCodes.NotFound -> s"Please reference: $apiUrl")
    }
  }

  override def close(): Unit = {
    Releasable.close(dataGroups)
  }
} 
Example 3
Source File: NavigatorBackend.scala    From daml   with Apache License 2.0 5 votes vote down vote up
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.navigator

import java.nio.file.{Files, Paths}
import java.util.UUID

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.daml.buildinfo.BuildInfo

object NavigatorBackend extends UIBackend {

  private val configFile = "frontend-config.js"
  override def customEndpoints: Set[CustomEndpoint[_]] = Set()
  override def customRoutes: List[Route] = List(frontendConfigRoute)
  override def applicationInfo: ApplicationInfo = ApplicationInfo(
    id = s"Navigator-${UUID.randomUUID().toString}",
    name = "Navigator",
    version = BuildInfo.Version,
  )
  override def banner: Option[String] =
    Some(
      raw"""   _  __          _           __
        |  / |/ /__ __  __(_)__ ____ _/ /____  ____
        | /    / _ `/ |/ / / _ `/ _ `/ __/ _ \/ __/
        |/_/|_/\_,_/|___/_/\_, /\_,_/\__/\___/_/
        |                 /___/
        |Version """.stripMargin + applicationInfo.version
    )

  
  private val frontendConfigRoute: Route = {
    path("api" / "config") {
      if (Files.exists(Paths.get(configFile)))
        getFromFile(configFile)
      else
        complete(StatusCodes.NotFound)
    }
  }
} 
Example 4
Source File: JsonRpcServer.scala    From mantis   with Apache License 2.0 5 votes vote down vote up
package io.iohk.ethereum.jsonrpc.server

import java.security.SecureRandom

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.HttpOriginRange
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{MalformedRequestContentRejection, RejectionHandler, Route}
import ch.megard.akka.http.cors.javadsl.CorsRejection
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._
import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import io.iohk.ethereum.jsonrpc.{JsonRpcController, JsonRpcErrors, JsonRpcRequest, JsonRpcResponse}
import io.iohk.ethereum.utils.Logger
import org.json4s.JsonAST.JInt
import org.json4s.{DefaultFormats, native}

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future

trait JsonRpcServer extends Json4sSupport {
  val jsonRpcController: JsonRpcController

  implicit val serialization = native.Serialization

  implicit val formats = DefaultFormats

  def corsAllowedOrigins: HttpOriginRange

  val corsSettings = CorsSettings.defaultSettings.copy(
    allowGenericHttpRequests = true,
    allowedOrigins = corsAllowedOrigins
  )

  implicit def myRejectionHandler: RejectionHandler =
    RejectionHandler.newBuilder()
      .handle {
        case _: MalformedRequestContentRejection =>
          complete((StatusCodes.BadRequest, JsonRpcResponse("2.0", None, Some(JsonRpcErrors.ParseError), JInt(0))))
        case _: CorsRejection =>
          complete(StatusCodes.Forbidden)
      }
      .result()

  val route: Route = cors(corsSettings) {
    (pathEndOrSingleSlash & post) {
      entity(as[JsonRpcRequest]) { request =>
        handleRequest(request)
      } ~ entity(as[Seq[JsonRpcRequest]]) { request =>
        handleBatchRequest(request)
      }
    }
  }

  
  def run(): Unit

  private def handleRequest(request: JsonRpcRequest) = {
    complete(jsonRpcController.handleRequest(request))
  }

  private def handleBatchRequest(requests: Seq[JsonRpcRequest]) = {
    complete(Future.sequence(requests.map(request => jsonRpcController.handleRequest(request))))
  }
}

object JsonRpcServer extends Logger {

  def apply(jsonRpcController: JsonRpcController, config: JsonRpcServerConfig, secureRandom: SecureRandom)
           (implicit actorSystem: ActorSystem): Either[String, JsonRpcServer] = config.mode match {
    case "http" => Right(new JsonRpcHttpServer(jsonRpcController, config)(actorSystem))
    case "https" => Right(new JsonRpcHttpsServer(jsonRpcController, config, secureRandom)(actorSystem))
    case _ => Left(s"Cannot start JSON RPC server: Invalid mode ${config.mode} selected")
  }

  trait JsonRpcServerConfig {
    val mode: String
    val enabled: Boolean
    val interface: String
    val port: Int
    val certificateKeyStorePath: Option[String]
    val certificateKeyStoreType: Option[String]
    val certificatePasswordFile: Option[String]
    val corsAllowedOrigins: HttpOriginRange
  }


} 
Example 5
Source File: Server.scala    From opencensus-scala   with Apache License 2.0 5 votes vote down vote up
package io.opencensus.scala.examples.akka.http

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.typesafe.scalalogging.LazyLogging
import io.opencensus.scala.akka.http.TracingDirective._
import io.opencensus.trace.AttributeValue
import org.slf4j.bridge.SLF4JBridgeHandler

import scala.util.{Failure, Success}

object Server extends App with LazyLogging {
  // Forward java.util.Logging to slf4j
  SLF4JBridgeHandler.removeHandlersForRootLogger()
  SLF4JBridgeHandler.install()

  implicit val system: ActorSystem = ActorSystem()
  import system.dispatcher

  val routes: Route = traceRequest { span =>
    complete {
      val attrValue = AttributeValue.stringAttributeValue("test")
      span.putAttribute("my-attribute", attrValue)
      "Hello opencensus"
    }
  }

  logger.info("Binding...")
  Http().bindAndHandle(routes, "0.0.0.0", 8080).onComplete {
    case Success(bound) =>
      logger.info(s"Bound to ${bound.localAddress}")
    case Failure(e) =>
      logger.error("Failed to bind", e)
  }
} 
Example 6
Source File: S2GraphMutateRoute.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.http

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ExceptionHandler, Route}
import com.fasterxml.jackson.core.JsonParseException
import org.apache.s2graph.core.rest.RequestParser
import org.apache.s2graph.core.storage.MutateResponse
import org.apache.s2graph.core.{GraphElement, S2Graph}
import org.slf4j.LoggerFactory
import play.api.libs.json.{JsValue, Json}

import scala.concurrent.{ExecutionContext, Future}

trait S2GraphMutateRoute extends PlayJsonSupport {

  val s2graph: S2Graph
  val logger = LoggerFactory.getLogger(this.getClass)

  lazy val parser = new RequestParser(s2graph)

  lazy val exceptionHandler = ExceptionHandler {
    case ex: JsonParseException => complete(StatusCodes.BadRequest -> ex.getMessage)
    case ex: java.lang.IllegalArgumentException => complete(StatusCodes.BadRequest -> ex.getMessage)
  }

  lazy val mutateVertex = path("vertex" / Segments) { params =>
    implicit val ec = s2graph.ec

    val (operation, serviceNameOpt, columnNameOpt) = params match {
      case operation :: serviceName :: columnName :: Nil => (operation, Option(serviceName), Option(columnName))
      case operation :: Nil => (operation, None, None)
      case _ => throw new RuntimeException("invalid params")
    }

    entity(as[JsValue]) { payload =>
      val future = vertexMutate(payload, operation, serviceNameOpt, columnNameOpt).map(Json.toJson(_))

      complete(future)
    }
  }

  lazy val mutateEdge = path("edge" / Segment) { operation =>
    implicit val ec = s2graph.ec

    entity(as[JsValue]) { payload =>
      val future = edgeMutate(payload, operation, withWait = true).map(Json.toJson(_))

      complete(future)
    }
  }

  def vertexMutate(jsValue: JsValue,
                   operation: String,
                   serviceNameOpt: Option[String] = None,
                   columnNameOpt: Option[String] = None,
                   withWait: Boolean = true)(implicit ec: ExecutionContext): Future[Seq[Boolean]] = {
    val vertices = parser.toVertices(jsValue, operation, serviceNameOpt, columnNameOpt)

    val verticesToStore = vertices.filterNot(_.isAsync)

    s2graph.mutateVertices(verticesToStore, withWait).map(_.map(_.isSuccess))
  }

  def edgeMutate(elementsWithTsv: Seq[(GraphElement, String)], withWait: Boolean)(implicit ec: ExecutionContext): Future[Seq[Boolean]] = {
    val elementWithIdxs = elementsWithTsv.zipWithIndex
    val (elementSync, elementAsync) = elementWithIdxs.partition { case ((element, tsv), idx) => !element.isAsync }

    val retToSkip = elementAsync.map(_._2 -> MutateResponse.Success)
    val (elementsToStore, _) = elementSync.map(_._1).unzip
    val elementsIdxToStore = elementSync.map(_._2)

    s2graph.mutateElements(elementsToStore, withWait).map { mutateResponses =>
      elementsIdxToStore.zip(mutateResponses) ++ retToSkip
    }.map(_.sortBy(_._1).map(_._2.isSuccess))
  }

  def edgeMutate(jsValue: JsValue, operation: String, withWait: Boolean)(implicit ec: ExecutionContext): Future[Seq[Boolean]] = {
    val edgesWithTsv = parser.parseJsonFormat(jsValue, operation)
    edgeMutate(edgesWithTsv, withWait)
  }

  // expose routes
  lazy val mutateRoute: Route =
    post {
      concat(
        handleExceptions(exceptionHandler) {
          mutateVertex
        },
        handleExceptions(exceptionHandler) {
          mutateEdge
        }
      )
    }

} 
Example 7
Source File: Server.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.http

import java.time.Instant

import scala.language.postfixOps
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.concurrent.duration.Duration
import scala.util.{Failure, Success}
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import com.typesafe.config.ConfigFactory
import org.apache.s2graph.core.S2Graph
import org.slf4j.LoggerFactory

object Server extends App
  with S2GraphTraversalRoute
  with S2GraphAdminRoute
  with S2GraphMutateRoute
  with S2GraphQLRoute {

  implicit val system: ActorSystem = ActorSystem("S2GraphHttpServer")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val executionContext: ExecutionContext = system.dispatcher

  val config = ConfigFactory.load()

  override val s2graph = new S2Graph(config)
  override val logger = LoggerFactory.getLogger(this.getClass)

  val port = sys.props.get("http.port").fold(8000)(_.toInt)
  val interface = sys.props.get("http.interface").fold("0.0.0.0")(identity)

  val startAt = System.currentTimeMillis()

  def uptime = System.currentTimeMillis() - startAt

  def serverHealth = s"""{ "port": ${port}, "interface": "${interface}", "started_at": ${Instant.ofEpochMilli(startAt)}, "uptime": "${uptime} millis" """

  def health = HttpResponse(status = StatusCodes.OK, entity = HttpEntity(ContentTypes.`application/json`, serverHealth))

  // Allows you to determine routes to expose according to external settings.
  lazy val routes: Route = concat(
    pathPrefix("graphs")(traversalRoute),
    pathPrefix("mutate")(mutateRoute),
    pathPrefix("admin")(adminRoute),
    pathPrefix("graphql")(graphqlRoute),
    get(complete(health))
  )

  val binding: Future[Http.ServerBinding] = Http().bindAndHandle(routes, interface, port)
  binding.onComplete {
    case Success(bound) => logger.info(s"Server online at http://${bound.localAddress.getHostString}:${bound.localAddress.getPort}/")
    case Failure(e) => logger.error(s"Server could not start!", e)
  }

  scala.sys.addShutdownHook { () =>
    s2graph.shutdown()
    system.terminate()
    logger.info("System terminated")
  }

  Await.result(system.whenTerminated, Duration.Inf)
} 
Example 8
Source File: S2GraphTraversalRoute.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.http

import org.apache.s2graph.core.S2Graph
import org.apache.s2graph.core.rest.RestHandler.CanLookup
import org.slf4j.LoggerFactory
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model._
import org.apache.s2graph.core.GraphExceptions.{BadQueryException, JsonParseException}
import org.apache.s2graph.core.rest.RestHandler
import play.api.libs.json._

object S2GraphTraversalRoute {

  import scala.collection._

  implicit val akkHttpHeaderLookup = new CanLookup[immutable.Seq[HttpHeader]] {
    override def lookup(m: immutable.Seq[HttpHeader], key: String): Option[String] = m.find(_.name() == key).map(_.value())
  }
}

trait S2GraphTraversalRoute extends PlayJsonSupport {

  import S2GraphTraversalRoute._

  val s2graph: S2Graph
  val logger = LoggerFactory.getLogger(this.getClass)

  implicit lazy val ec = s2graph.ec
  lazy val restHandler = new RestHandler(s2graph)

  // The `/graphs/*` APIs are implemented to be branched from the existing restHandler.doPost.
  // Implement it first by delegating that function.
  lazy val delegated: Route = {
    entity(as[String]) { body =>
      logger.info(body)

      extractRequest { request =>
        val result = restHandler.doPost(request.uri.toRelative.toString(), body, request.headers)
        val responseHeaders = result.headers.toList.map { case (k, v) => RawHeader(k, v) }

        val f = result.body.map(StatusCodes.OK -> _).recover {
          case BadQueryException(msg, _) => StatusCodes.BadRequest -> Json.obj("error" -> msg)
          case JsonParseException(msg) => StatusCodes.BadRequest -> Json.obj("error" -> msg)
          case e: Exception => StatusCodes.InternalServerError -> Json.obj("error" -> e.toString)
        }

        respondWithHeaders(responseHeaders)(complete(f))
      }
    }
  }

  // expose routes
  lazy val traversalRoute: Route =
    post {
      concat(
        delegated // getEdges, experiments, etc.
      )
    }
} 
Example 9
Source File: MatcherApiRouteV1.scala    From matcher   with MIT License 5 votes vote down vote up
package com.wavesplatform.dex.api.http.routes

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.directives.FutureDirectives
import akka.http.scaladsl.server.{Directive1, Route}
import com.wavesplatform.dex.Matcher
import com.wavesplatform.dex.api.http.entities.{HttpV1OrderBook, InfoNotFound}
import com.wavesplatform.dex.api.http.{HasStatusBarrier, OrderBookHttpInfo}
import com.wavesplatform.dex.api.routes.{ApiRoute, AuthRoute, PathMatchers}
import com.wavesplatform.dex.domain.asset.AssetPair
import com.wavesplatform.dex.domain.utils.ScorexLogging
import com.wavesplatform.dex.error.{ErrorFormatterContext, MatcherError}
import com.wavesplatform.dex.model.{AssetPairBuilder, MatcherModel}
import io.swagger.annotations.{Api, ApiImplicitParam, ApiImplicitParams, ApiOperation}
import javax.ws.rs.Path

@Path("/api/v1")
@Api(value = "/api v1/")
case class MatcherApiRouteV1(assetPairBuilder: AssetPairBuilder,
                             orderBookHttpInfo: OrderBookHttpInfo,
                             matcherStatus: () => Matcher.Status,
                             apiKeyHash: Option[Array[Byte]])(implicit val errorContext: ErrorFormatterContext)
    extends ApiRoute
    with AuthRoute
    with HasStatusBarrier
    with ScorexLogging {

  import PathMatchers._

  override lazy val route: Route = pathPrefix("api" / "v1") {
    matcherStatusBarrier {
      getOrderBook
    }
  }

  private def withAssetPair(p: AssetPair,
                            redirectToInverse: Boolean,
                            suffix: String = "",
                            formatError: MatcherError => ToResponseMarshallable = InfoNotFound.apply): Directive1[AssetPair] = {
    FutureDirectives.onSuccess { assetPairBuilder.validateAssetPair(p).value } flatMap {
      case Right(_) => provide(p)
      case Left(e) if redirectToInverse =>
        FutureDirectives.onSuccess { assetPairBuilder.validateAssetPair(p.reverse).value } flatMap {
          case Right(_) => redirect(s"/api/v1/${p.priceAssetStr}/${p.amountAssetStr}$suffix", StatusCodes.MovedPermanently)
          case Left(_)  => complete(formatError(e))
        }
      case Left(e) => complete { formatError(e) }
    }
  }

  @Path("/orderbook/{amountAsset}/{priceAsset}")
  @ApiOperation(
    value = "Get Order Book for a given Asset Pair",
    notes = "Get Order Book for a given Asset Pair",
    httpMethod = "GET",
    response = classOf[HttpV1OrderBook]
  )
  @ApiImplicitParams(
    Array(
      new ApiImplicitParam(name = "amountAsset", value = "Amount Asset Id in Pair, or 'WAVES'", dataType = "string", paramType = "path"),
      new ApiImplicitParam(name = "priceAsset", value = "Price Asset Id in Pair, or 'WAVES'", dataType = "string", paramType = "path"),
      new ApiImplicitParam(name = "depth",
                           value = "Limit the number of bid/ask records returned",
                           required = false,
                           dataType = "integer",
                           paramType = "query")
    )
  )
  def getOrderBook: Route = (path("orderbook" / AssetPairPM) & get) { p =>
    parameters('depth.as[Int].?) { depth =>
      withAssetPair(p, redirectToInverse = true) { pair =>
        complete { orderBookHttpInfo.getHttpView(pair, MatcherModel.Denormalized, depth) }
      }
    }
  }
} 
Example 10
Source File: CompositeHttpService.scala    From matcher   with MIT License 5 votes vote down vote up
package com.wavesplatform.dex.api.http

import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.RouteResult.Complete
import akka.http.scaladsl.server.directives.{DebuggingDirectives, LoggingMagnet}
import akka.http.scaladsl.server.{Directive0, Route, RouteResult}
import com.wavesplatform.dex.Application
import com.wavesplatform.dex.api.routes.ApiRoute
import com.wavesplatform.dex.domain.utils.ScorexLogging
import com.wavesplatform.dex.settings.RestAPISettings

class CompositeHttpService(apiTypes: Set[Class[_]], routes: Seq[ApiRoute], settings: RestAPISettings) extends ScorexLogging {

  private val swaggerService    = new SwaggerDocService(apiTypes, s"${settings.address}:${settings.port}")
  private val redirectToSwagger = redirect("/api-docs/index.html", StatusCodes.PermanentRedirect)
  private val swaggerRoute: Route = swaggerService.routes ~
    (pathEndOrSingleSlash | path("swagger"))(redirectToSwagger) ~
    pathPrefix("api-docs") {
      pathEndOrSingleSlash(redirectToSwagger) ~
        getFromResourceDirectory(s"META-INF/resources/webjars/swagger-ui/${SwaggerUiVersion.VersionString}", Application.getClass.getClassLoader)
    }

  val compositeRoute: Route        = extendRoute(routes.map(_.route).reduce(_ ~ _)) ~ swaggerRoute ~ complete(StatusCodes.NotFound)
  val loggingCompositeRoute: Route = DebuggingDirectives.logRequestResult(LoggingMagnet(_ => logRequestResponse))(compositeRoute)

  private def logRequestResponse(req: HttpRequest)(res: RouteResult): Unit = res match {
    case Complete(resp) =>
      val msg = s"HTTP ${resp.status.value} from ${req.method.value} ${req.uri}"
      if (resp.status == StatusCodes.OK) log.info(msg) else log.warn(msg)
    case _ =>
  }

  private val corsAllowedHeaders = (if (settings.apiKeyDifferentHost) List("api_key", "X-API-Key") else List.empty[String]) ++
    Seq("Authorization", "Content-Type", "X-Requested-With", "Timestamp", "Signature")

  private def corsAllowAll: Directive0 = if (settings.cors) respondWithHeader(`Access-Control-Allow-Origin`.*) else pass

  private def extendRoute(base: Route): Route =
    if (settings.cors) { ctx =>
      val extendedRoute = corsAllowAll(base) ~ options {
        respondWithDefaultHeaders(
          `Access-Control-Allow-Credentials`(true),
          `Access-Control-Allow-Headers`(corsAllowedHeaders),
          `Access-Control-Allow-Methods`(OPTIONS, POST, PUT, GET, DELETE)
        )(corsAllowAll(complete(StatusCodes.OK)))
      }

      extendedRoute(ctx)
    } else base
} 
Example 11
Source File: akkaHttp.scala    From sup   with Apache License 2.0 5 votes vote down vote up
package sup.modules

import akka.http.scaladsl.marshalling.ToEntityMarshaller
import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives.{path => akkaPath, _}
import akka.http.scaladsl.server.Route
import cats.effect.Effect
import cats.syntax.functor._
import cats.syntax.reducible._
import cats.~>
import cats.Functor
import cats.Reducible
import sup.HealthCheck
import sup.HealthResult

import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
import akka.http.scaladsl.model.HttpRequest

object akkahttp {

  
  def healthCheckRoutes[F[_]: Effect, H[_]: Reducible](
    healthCheck: HealthCheck[F, H],
    path: String = "health-check"
  )(
    implicit marshaller: ToEntityMarshaller[HealthResult[H]]
  ): Route =
    akkaPath(path) {
      get {
        onComplete(Effect[F].toIO(healthCheckResponse(healthCheck)).unsafeToFuture()) {
          case Success(response) => complete(response)
          case Failure(error)    => failWith(error)
        }
      }
    }

  def healthCheckResponse[F[_]: Functor, H[_]: Reducible](
    healthCheck: HealthCheck[F, H]
  ): F[(StatusCode, HealthResult[H])] =
    healthCheck.check.map { check =>
      if (check.value.reduce.isHealthy) StatusCodes.OK -> check
      else StatusCodes.ServiceUnavailable -> check
    }

  def healthCheckRoutesWithContext[F[_]: Functor, H[_]: Reducible, R](
    healthCheck: HealthCheck[F, H],
    path: String = "health-check"
  )(
    run: HttpRequest => F ~> Future
  )(
    implicit marshaller: ToEntityMarshaller[HealthResult[H]]
  ): Route =
    akkaPath(path) {
      get {
        extractRequest { request =>
          onComplete(run(request)(healthCheckResponse(healthCheck))) {
            case Success(response) => complete(response)
            case Failure(error)    => failWith(error)
          }
        }
      }
    }
} 
Example 12
Source File: HttpRoute.scala    From akka-http-rest   with MIT License 5 votes vote down vote up
package me.archdev.restapi.http

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import me.archdev.restapi.core.profiles.UserProfileService
import me.archdev.restapi.http.routes.{ AuthRoute, ProfileRoute }
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._
import me.archdev.restapi.core.auth.AuthService

import scala.concurrent.ExecutionContext

class HttpRoute(
    userProfileService: UserProfileService,
    authService: AuthService,
    secretKey: String
)(implicit executionContext: ExecutionContext) {

  private val usersRouter = new ProfileRoute(secretKey, userProfileService)
  private val authRouter  = new AuthRoute(authService)

  val route: Route =
    cors() {
      pathPrefix("v1") {
        usersRouter.route ~
        authRouter.route
      } ~
      pathPrefix("healthcheck") {
        get {
          complete("OK")
        }
      }
    }

} 
Example 13
Source File: AuthRouteTest.scala    From akka-http-rest   with MIT License 5 votes vote down vote up
package me.archdev.http.routes

import akka.http.scaladsl.model.{HttpEntity, MediaTypes}
import akka.http.scaladsl.server.Route
import me.archdev.BaseServiceTest
import me.archdev.restapi.core.auth.AuthService
import me.archdev.restapi.http.routes.AuthRoute
import org.mockito.Mockito._

import scala.concurrent.Future

class AuthRouteTest extends BaseServiceTest {

  "AuthRoute" when {

    "POST /auth/signIn" should {

      "return 200 and token if sign in successful" in new Context {
        when(authService.signIn("test", "test")).thenReturn(Future.successful(Some("token")))
        val requestEntity = HttpEntity(MediaTypes.`application/json`, s"""{"login": "test", "password": "test"}""")

        Post("/auth/signIn", requestEntity) ~> authRoute ~> check {
          responseAs[String] shouldBe "\"token\""
          status.intValue() shouldBe 200
        }
      }

      "return 400 if signIn unsuccessful" in new Context {
        when(authService.signIn("test", "test")).thenReturn(Future.successful(None))
        val requestEntity = HttpEntity(MediaTypes.`application/json`, s"""{"login": "test", "password": "test"}""")

        Post("/auth/signIn", requestEntity) ~> authRoute ~> check {
          status.intValue() shouldBe 400
        }
      }

    }

    "POST /auth/signUp" should {

      "return 201 and token" in new Context {
        when(authService.signUp("test", "test", "test")).thenReturn(Future.successful("token"))
        val requestEntity = HttpEntity(MediaTypes.`application/json`, s"""{"username": "test", "email": "test", "password": "test"}""")

        Post("/auth/signUp", requestEntity) ~> authRoute ~> check {
          responseAs[String] shouldBe "\"token\""
          status.intValue() shouldBe 201
        }
      }

    }

  }

  trait Context {
    val authService: AuthService = mock[AuthService]
    val authRoute: Route = new AuthRoute(authService).route
  }

} 
Example 14
Source File: HTTPResponseStream.scala    From akka_streams_tutorial   with MIT License 5 votes vote down vote up
package akkahttp

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives.{complete, get, logRequestResult, path, _}
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.ThrottleMode
import akka.stream.scaladsl.{Flow, Sink, Source}
import com.typesafe.config.ConfigFactory
import spray.json.DefaultJsonProtocol

import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{Failure, Success}


object HTTPResponseStream extends App with DefaultJsonProtocol with SprayJsonSupport {
  implicit val system = ActorSystem("HTTPResponseStream")
  implicit val executionContext = system.dispatcher

  //JSON Protocol and streaming support
  final case class ExamplePerson(name: String)

  implicit def examplePersonFormat = jsonFormat1(ExamplePerson.apply)

  implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json()

  val (address, port) = ("127.0.0.1", 8080)
  server(address, port)
  client(address, port)

  def client(address: String, port: Int): Unit = {
    val requestParallelism = ConfigFactory.load.getInt("akka.http.host-connection-pool.max-connections")

    val requests: Source[HttpRequest, NotUsed] = Source
      .fromIterator(() =>
        Range(0, requestParallelism).map(i => HttpRequest(uri = Uri(s"http://$address:$port/download/$i"))).iterator
      )

    // Run singleRequest and completely consume response elements
    def runRequestDownload(req: HttpRequest) =
      Http()
        .singleRequest(req)
        .flatMap { response =>
          val unmarshalled: Future[Source[ExamplePerson, NotUsed]] = Unmarshal(response).to[Source[ExamplePerson, NotUsed]]
          val source: Source[ExamplePerson, Future[NotUsed]] = Source.futureSource(unmarshalled)
          source.via(processorFlow).runWith(printSink)
        }

    requests
      .mapAsync(requestParallelism)(runRequestDownload)
      .runWith(Sink.ignore)
  }


  val printSink = Sink.foreach[ExamplePerson] { each: ExamplePerson => println(s"Client processed element: $each") }

  val processorFlow: Flow[ExamplePerson, ExamplePerson, NotUsed] = Flow[ExamplePerson].map {
    each: ExamplePerson => {
      //println(s"Process: $each")
      each
    }
  }


  def server(address: String, port: Int): Unit = {

    def routes: Route = logRequestResult("httpecho") {
      path("download" / Segment) { id: String =>
        get {
          println(s"Server received request with id: $id, stream response...")
          extractRequest { r: HttpRequest =>
            val finishedWriting = r.discardEntityBytes().future
            onComplete(finishedWriting) { done =>
              //Limit response by appending eg .take(5)
              val responseStream: Stream[ExamplePerson] = Stream.continually(ExamplePerson(s"request:$id"))
              complete(Source(responseStream).throttle(1, 1.second, 1, ThrottleMode.shaping))
            }
          }
        }
      }
    }

    val bindingFuture = Http().bindAndHandle(routes, address, port)
    bindingFuture.onComplete {
      case Success(b) =>
        println("Server started, listening on: " + b.localAddress)
      case Failure(e) =>
        println(s"Server could not bind to: $address:$port. Exception message: ${e.getMessage}")
        system.terminate()
    }
  }
} 
Example 15
Source File: SampleRoutes.scala    From akka_streams_tutorial   with MIT License 5 votes vote down vote up
package akkahttp

import java.io.File

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import org.slf4j.{Logger, LoggerFactory}

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.sys.process.Process
import scala.util.{Failure, Success}


object SampleRoutes extends App {
  val logger: Logger = LoggerFactory.getLogger(this.getClass)
  implicit val system = ActorSystem("SampleRoutes")
  implicit val executionContext = system.dispatcher


  def getFromBrowsableDir: Route = {
    val dirToBrowse = File.separator + "tmp"

    // pathPrefix allows loading dirs and files recursively
    pathPrefix("entries") {
      getFromBrowseableDirectory(dirToBrowse)
    }
  }

  def parseFormData: Route = path("post") {
    formFields('color, 'age.as[Int]) { (color, age) =>
      complete(s"The color is '$color' and the age is $age")
    }
  }

  def routes: Route = {
    getFromBrowsableDir ~ parseFormData
  }

  val bindingFuture = Http().bindAndHandle(routes, "127.0.0.1", 8000)

  bindingFuture.onComplete {
    case Success(b) =>
      println("Server started, listening on: " + b.localAddress)
    case Failure(e) =>
      println(s"Server could not bind to... Exception message: ${e.getMessage}")
      system.terminate()
  }

  def browserClient() = {
    val os = System.getProperty("os.name").toLowerCase
    if (os == "mac os x") Process("open ./src/main/resources/SampleRoutes.html").!
  }

  browserClient()

  sys.addShutdownHook {
    println("About to shutdown...")
    val fut = bindingFuture.map(serverBinding => serverBinding.terminate(hardDeadline = 3.seconds))
    println("Waiting for connections to terminate...")
    val onceAllConnectionsTerminated = Await.result(fut, 10.seconds)
    println("Connections terminated")
    onceAllConnectionsTerminated.flatMap { _ => system.terminate()
    }
  }
} 
Example 16
Source File: WebsocketServer.scala    From akka_streams_tutorial   with MIT License 5 votes vote down vote up
package alpakka.env

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.ws._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.WebSocketDirectives
import akka.stream.scaladsl.{Flow, Sink, Source}

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.util.{Failure, Success}


object WebsocketServer extends App with WebSocketDirectives {
  implicit val system = ActorSystem("WebsocketServer")
  implicit val executionContext = system.dispatcher

  val (address, port) = ("127.0.0.1", 6002)
  server(address, port)

  def server(address: String, port: Int) = {

    def echoFlow: Flow[Message, Message, Any] =
      Flow[Message].mapConcat {
        case tm: TextMessage =>
          println(s"Server received: $tm")
          TextMessage(Source.single("Echo: ") ++ tm.textStream) :: Nil
        case bm: BinaryMessage =>
          // ignore binary messages but drain content to avoid the stream being clogged
          bm.dataStream.runWith(Sink.ignore)
          Nil
      }

    val websocketRoute: Route =
      path("echo") {
        handleWebSocketMessages(echoFlow)
      }

    val bindingFuture = Http().bindAndHandle(websocketRoute, address, port)
    bindingFuture.onComplete {
      case Success(b) =>
        println("Server started, listening on: " + b.localAddress)
      case Failure(e) =>
        println(s"Server could not bind to $address:$port. Exception message: ${e.getMessage}")
        system.terminate()
    }

    sys.addShutdownHook {
      println("About to shutdown...")
      val fut = bindingFuture.map(serverBinding => serverBinding.terminate(hardDeadline = 3.seconds))
      println("Waiting for connections to terminate...")
      val onceAllConnectionsTerminated = Await.result(fut, 10.seconds)
      println("Connections terminated")
      onceAllConnectionsTerminated.flatMap { _ => system.terminate()
      }
    }
  }
} 
Example 17
Source File: UserRoutes.scala    From akka-http-slick-sample   with MIT License 5 votes vote down vote up
package net.softler.routes

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import net.softler.data.model.{JsonProtocol, User}
import net.softler.data.persistence.UserComponent

import scala.concurrent.ExecutionContext


class UserRoutes(repo: UserComponent#UserRepository)(implicit ex: ExecutionContext)
    extends JsonProtocol {

  val routes: Route = pathPrefix("user") {
    pathEndOrSingleSlash {
      get {
        complete(repo.all)
      } ~ post {
        entity(as[User]) { u =>
          complete(repo.insert(u))
        }
      }
    }
  }
} 
Example 18
Source File: SidechainRejectionApiRoute.scala    From Sidechains-SDK   with MIT License 5 votes vote down vote up
package com.horizen.api.http

import akka.actor.{ActorRef, ActorRefFactory}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import scorex.core.settings.RESTApiSettings

import scala.concurrent.ExecutionContext


case class SidechainRejectionApiRoute(basePath: String, path: String,
                                      override val settings: RESTApiSettings, sidechainNodeViewHolderRef: ActorRef)
                                     (implicit val context: ActorRefFactory, override val ec: ExecutionContext)
  extends SidechainApiRoute {

  override def route: Route =
    if (path.isEmpty)
      (pathPrefix(basePath)) {
        SidechainApiError(StatusCodes.NotFound, "NotFound").complete("The requested resource could not be found.")
      }
    else (pathPrefix(basePath) & path(path)) {
      SidechainApiError(StatusCodes.NotFound, "NotFound").complete("The requested resource could not be found.")
    }

} 
Example 19
Source File: ApplicationApiRoute.scala    From Sidechains-SDK   with MIT License 5 votes vote down vote up
package com.horizen.api.http

import akka.actor.{ActorRef, ActorRefFactory}
import akka.pattern.ask
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.RouteDirectives
import com.horizen.SidechainNodeViewHolder.ReceivableMessages.GetDataFromCurrentSidechainNodeView
import com.horizen.node.SidechainNodeView
import scorex.core.settings.RESTApiSettings
import scorex.core.utils.ScorexEncoding

import scala.concurrent.{Await, ExecutionContext}
import scala.collection.JavaConverters._
import scala.util.{Failure, Success, Try}

case class ApplicationApiRoute(override val settings: RESTApiSettings, sidechainNodeViewHolderRef: ActorRef, applicationApiGroup: ApplicationApiGroup)
                              (implicit val context: ActorRefFactory, override val ec: ExecutionContext)
  extends SidechainApiRoute
    with ScorexEncoding {


  override def route: Route = convertRoutes

  private def convertRoutes: Route = {

    applicationApiGroup.setApplicationNodeViewProvider(new ApplicationNodeViewProvider {

      override def getSidechainNodeView: Try[SidechainNodeView] = retrieveSidechainNodeView()

    })

    var listOfAppApis: List[Route] = applicationApiGroup.getRoutes.asScala.toList.map(r => r.asScala)

    pathPrefix(applicationApiGroup.basePath()) {
      listOfAppApis.reduceOption(_ ~ _).getOrElse(RouteDirectives.reject)
    }
  }

  private def retrieveSidechainNodeView(): Try[SidechainNodeView] = {
    def f(v: SidechainNodeView) = v

    def fut = (sidechainNodeViewHolderRef ? GetDataFromCurrentSidechainNodeView(f))
      .mapTo[SidechainNodeView]

    try {
      var result = Await.result(fut, settings.timeout)
      Success(result)
    } catch {
      case e: Throwable => Failure(e)
    }
  }

} 
Example 20
Source File: ApiResponseUtil.scala    From Sidechains-SDK   with MIT License 5 votes vote down vote up
package com.horizen.api.http

import akka.http.javadsl.model.{ContentTypes, HttpEntities, StatusCodes}
import akka.http.javadsl.server
import akka.http.javadsl.server.Directives
import akka.http.scaladsl.server.Route
import com.horizen.serialization.SerializationUtil

object ApiResponseUtil {

  def toResponse(response: ApiResponse): Route = {
    response match {
      case _: SuccessResponse => SidechainApiResponse(SerializationUtil.serializeWithResult(response))
      case e: ErrorResponse =>
        e.exception match {
          case Some(thr) =>
            val msg = thr.getMessage
            if (msg != null && !msg.isEmpty)
              SidechainApiResponse(SerializationUtil.serializeErrorWithResult(e.code, e.description, msg))
            else SidechainApiResponse(SerializationUtil.serializeErrorWithResult(e.code, e.description, ""))
          case None => SidechainApiResponse(SerializationUtil.serializeErrorWithResult(e.code, e.description, ""))
        }
    }
  }

  def toResponseAsJava(response: ApiResponse): server.Route = {
    response match {
      case _: SuccessResponse => Directives.complete(StatusCodes.OK, HttpEntities.create(ContentTypes.APPLICATION_JSON, SerializationUtil.serializeWithResult(response)))
      case e: ErrorResponse =>
        e.exception match {
          case Some(thr) =>
            val msg = thr.getMessage
            if (msg != null && !msg.isEmpty)
              Directives.complete(StatusCodes.OK, HttpEntities.create(ContentTypes.APPLICATION_JSON, SerializationUtil.serializeErrorWithResult(e.code, e.description, msg)))
            else
              Directives.complete(StatusCodes.OK, HttpEntities.create(ContentTypes.APPLICATION_JSON, SerializationUtil.serializeErrorWithResult(e.code, e.description, "")))
          case None =>
            Directives.complete(StatusCodes.OK, HttpEntities.create(ContentTypes.APPLICATION_JSON, SerializationUtil.serializeErrorWithResult(e.code, e.description, "")))
        }
    }
  }
} 
Example 21
Source File: ApplicationApiRouteTest.scala    From Sidechains-SDK   with MIT License 5 votes vote down vote up
package com.horizen.api.http

import akka.http.scaladsl.model.{ContentTypes, StatusCodes}
import akka.http.scaladsl.server.Route
import org.junit.Assert.{assertEquals, assertTrue}
import scala.collection.JavaConverters._

class ApplicationApiRouteTest extends SidechainApiRouteTest {

  override val basePath = "/simpleApi/"

  "The Api should to" should {

    "reject and reply with http error" in {

      Get(basePath) ~> Route.seal(applicationApiRoute) ~> check {
        status.intValue() shouldBe StatusCodes.NotFound.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
      }
    }

    "reply at /allSecrets" in {

      Post(basePath + "allSecrets") ~> applicationApiRoute ~> check {
        status.intValue() shouldBe StatusCodes.OK.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
        mapper.readTree(entityAs[String]).get("result") match {
          case result =>
            assertEquals(1, result.elements().asScala.length)
            assertTrue(result.get("secrets").isArray)
            assertEquals(2, result.get("secrets").elements().asScala.length)
            result.get("secrets").elements().asScala.toList.foreach(node => {
              assertTrue(node.isObject)
              assertEquals(0, node.elements().asScala.length)
            })
          case _ => fail("Serialization failed for object SidechainApiResponseBody")
        }
      }

      sidechainApiMockConfiguration.setShould_nodeViewHolder_GetDataFromCurrentSidechainNodeView_reply(false)
      Post(basePath + "allSecrets") ~> applicationApiRoute ~> check {
        status.intValue() shouldBe StatusCodes.OK.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
        assertsOnSidechainErrorResponseSchema(entityAs[String], new ErrorAllSecrets("", None).code())
      }
    }
  }
} 
Example 22
Source File: HistoryApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import akka.actor.{ ActorRef, ActorRefFactory }
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import encry.api.http.DataHolderForApi.{
  GetDataFromHistory,
  GetFullBlockByIdCommand,
  GetLastHeaderIdAtHeightHelper,
  GetLastHeadersHelper,
  GetMinerStatus
}
import encry.local.miner.Miner.MinerStatus
import encry.settings.RESTApiSettings
import encry.view.history.History
import io.circe.syntax._
import org.encryfoundation.common.modifiers.history.{ Block, Header }
import org.encryfoundation.common.utils.Algos

case class HistoryApiRoute(dataHolder: ActorRef, settings: RESTApiSettings, nodeId: Array[Byte])(
  implicit val context: ActorRefFactory
) extends EncryBaseApiRoute {

  override val route: Route = pathPrefix("history") {
    getHeaderIdsR ~
      getLastHeadersR ~
      getHeadersIdsAtHeightR ~
      getBlockHeaderByHeaderIdR ~
      getBlockTransactionsByHeaderIdR ~
      getFullBlockByHeaderIdR ~
      candidateBlockR
  }

  def getHeaderIdsR: Route = (pathEndOrSingleSlash & get & paging) { (offset, limit) =>
    (dataHolder ? GetDataFromHistory).mapTo[History]
      .map {
      _.getHeaderIds(offset, limit).map(Algos.encode).asJson
    }.okJson()
  }

  def getLastHeadersR: Route = (pathPrefix("lastHeaders" / IntNumber) & get) { qty =>
    (dataHolder ? GetLastHeadersHelper(qty)).mapTo[IndexedSeq[Header]].map(_.asJson).okJson()
  }

  def getHeadersIdsAtHeightR: Route = (pathPrefix("at" / IntNumber) & get) { height =>
    (dataHolder ? GetLastHeaderIdAtHeightHelper(height))
      .mapTo[Seq[String]]
      .map(_.asJson).okJson()
  }

  def getBlockHeaderByHeaderIdR: Route = (modifierId & pathPrefix("header") & get) { id =>
    (dataHolder ? GetFullBlockByIdCommand(Right(id))).mapTo[Option[Block]].map(_.map(x => x.header.asJson)).okJson()
  }

  def getBlockTransactionsByHeaderIdR: Route = (modifierId & pathPrefix("transactions") & get) { id =>
    (dataHolder ? GetFullBlockByIdCommand(Right(id))).mapTo[Option[Block]].map(_.map(_.payload.txs.asJson)).okJson()
  }

  def candidateBlockR: Route = (path("candidateBlock") & pathEndOrSingleSlash & get) {
    (dataHolder ? GetMinerStatus).mapTo[MinerStatus].map(_.json).okJson()
  }

  def getFullBlockByHeaderIdR: Route = (modifierId & get) { id =>
    (dataHolder ? GetFullBlockByIdCommand(Right(id))).mapTo[Option[Block]].map(_.asJson).okJson()
  }
} 
Example 23
Source File: EncryBaseApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import akka.http.scaladsl.server.{Directive, Directive1, Route}
import encry.api.http.ApiRoute
import io.circe.Json
import org.encryfoundation.common.crypto.encoding.Base58Check
import org.encryfoundation.common.modifiers.mempool.transaction.EncryAddress.Address
import org.encryfoundation.common.utils.Algos
import org.encryfoundation.common.utils.TaggedTypes.{ADKey, ModifierId}

import scala.concurrent.{ExecutionContextExecutor, Future}
import scala.util.Success

trait EncryBaseApiRoute extends ApiRoute {

  implicit val ec: ExecutionContextExecutor = context.dispatcher

  protected def toJsonResponse(js: Json): Route = {
    val resp = complete(HttpEntity(ContentTypes.`application/json`, js.spaces2))
    withCors(resp)
  }

  protected def toJsonResponse(fn: Future[Json]): Route = onSuccess(fn) { toJsonResponse }

  protected def toJsonOptionalResponse(fn: Future[Option[Json]]): Route = {
    onSuccess(fn) {
      case Some(v) => toJsonResponse(v)
      case None => withCors(complete(StatusCodes.NotFound))
    }
  }

  val paging: Directive[(Int, Int)] = parameters("offset".as[Int] ? 0, "limit".as[Int] ? 50)

  val modifierId: Directive1[ModifierId] = pathPrefix(Segment).flatMap { h =>
    Algos.decode(h) match {
      case Success(header) => provide(ModifierId @@ header)
      case _ => reject
    }
  }

  implicit class OkJsonResp(fn: Future[Json]) {
    def okJson(): Route = toJsonResponse(fn)
  }

  implicit class OkJsonOptResp(fn: Future[Option[Json]]) {
    def okJson(): Route = toJsonOptionalResponse(fn)
  }
} 
Example 24
Source File: NodeRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import akka.actor.{ActorRef, ActorRefFactory}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import encry.api.http.DataHolderForApi._
import encry.settings.RESTApiSettings

case class NodeRoute(dataHolder: ActorRef, settings: RESTApiSettings)(implicit val context: ActorRefFactory)
    extends EncryBaseApiRoute {

  override def route: Route = pathPrefix("node") {
    WebRoute.authRoute(nodeStartMiningR ~ nodeStopMiningR ~ nodeShutdownR, settings)
  }

  def nodeStartMiningR: Route = (path("startMining") & get) {
    dataHolder ! StartMinerApiMessage
    withCors(complete(StatusCodes.OK))
  }

  def nodeStopMiningR: Route = (path("stopMining") & get) {
    dataHolder ! StopMinerApiMessage
    withCors(complete(StatusCodes.OK))
  }

  def nodeShutdownR: Route = (path("shutdown") & get) {
    dataHolder ! ShutdownNode
    withCors(complete(StatusCodes.OK))
  }

} 
Example 25
Source File: InfoApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import java.net.InetSocketAddress
import akka.actor.{ ActorRef, ActorRefFactory }
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import encry.api.http.DataHolderForApi._
import encry.local.miner.Miner.MinerStatus
import encry.settings._
import encry.utils.NetworkTimeProvider
import io.circe.Json
import io.circe.syntax._
import io.circe.generic.auto._
import org.encryfoundation.common.modifiers.history.{ Block, Header }
import org.encryfoundation.common.utils.Algos
import org.encryfoundation.common.utils.constants.Constants

case class InfoApiRoute(dataHolder: ActorRef,
                        settings: RESTApiSettings,
                        nodeId: Array[Byte],
                        timeProvider: NetworkTimeProvider)(implicit val context: ActorRefFactory)
    extends EncryBaseApiRoute {

  override val route: Route = (path("info") & get) {
    (dataHolder ? GetAllInfoHelper)
      .mapTo[Json]
      .okJson()
  }
}

object InfoApiRoute {

  def makeInfoJson(nodeId: Array[Byte],
                   minerInfo: MinerStatus,
                   connectedPeersLength: Int,
                   readers: Readers,
                   stateType: String,
                   nodeName: String,
                   knownPeers: Seq[InetSocketAddress],
                   storage: String,
                   nodeUptime: Long,
                   mempoolSize: Int,
                   connectWithOnlyKnownPeer: Boolean,
                   header: Option[Header],
                   block: Option[Block],
                   constants: Constants
                  ): Json = {
    val stateVersion: Option[String] = readers.s.map(_.version).map(Algos.encode)
    val stateRoot: Option[String] = readers.s.map(_.tree.rootHash).map(Algos.encode)
    val prevFullHeaderId: String = block.map(b => Algos.encode(b.header.parentId)).getOrElse("")
    InfoApi(
      nodeName,
      stateType,
      block.map(_.header.difficulty.toString).getOrElse(constants.InitialDifficulty.toString),
      block.map(_.encodedId).getOrElse(""),
      header.map(_.encodedId).getOrElse(""),
      connectedPeersLength,
      mempoolSize,
      prevFullHeaderId,
      block.map(_.header.height).getOrElse(0),
      header.map(_.height).getOrElse(0),
      stateVersion.getOrElse(""),
      nodeUptime,
      storage,
      connectWithOnlyKnownPeer,
      minerInfo.isMining,
      knownPeers.map { x =>
        x.getHostName + ":" + x.getPort
      },
      stateRoot.getOrElse("")
    ).asJson
  }
} 
Example 26
Source File: TransactionsApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import akka.actor.{ ActorRef, ActorRefFactory }
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import encry.settings.RESTApiSettings
import encry.view.mempool.MemoryPool.NewTransaction
import org.encryfoundation.common.modifiers.mempool.transaction.Transaction

case class TransactionsApiRoute(dataHolder: ActorRef, memoryPoolRef: ActorRef, settings: RESTApiSettings)(
  implicit val context: ActorRefFactory
) extends EncryBaseApiRoute
    with FailFastCirceSupport {

  override val route: Route = pathPrefix("transactions") {
    WebRoute.authRoute(defaultTransferTransactionR, settings)
  }

  def defaultTransferTransactionR: Route = path("send") {
    post(entity(as[Transaction]) { tx =>
      complete {
        memoryPoolRef ! NewTransaction(tx)
        StatusCodes.OK
      }
    })
  }
} 
Example 27
Source File: PeersApiRoute.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http.routes

import java.net.{InetAddress, InetSocketAddress}
import akka.actor.{ActorRef, ActorRefFactory}
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import encry.api.http.DataHolderForApi._
import encry.api.http.routes.PeersApiRoute.PeerInfoResponse
import encry.network.BlackList.{BanReason, BanTime, BanType}
import encry.network.ConnectedPeersCollection.PeerInfo
import encry.settings.RESTApiSettings
import io.circe.Encoder
import io.circe.generic.semiauto._
import io.circe.syntax._
import scala.util.{Failure, Success, Try}

case class PeersApiRoute(override val settings: RESTApiSettings, dataHolder: ActorRef)(
  implicit val context: ActorRefFactory
) extends EncryBaseApiRoute {

  override lazy val route: Route = pathPrefix("peers") {
    connectedPeers ~ allPeers ~ bannedList ~ WebRoute.authRoute(connectPeer ~ removeFromBan, settings)
  }

  def allPeers: Route = (path("all") & get) {
    (dataHolder ? GetAllPeers)
      .mapTo[Seq[InetSocketAddress]]
      .map(_.map(_.toString).asJson).okJson()
  }

  def connectedPeers: Route = (path("connected") & get) {
    (dataHolder ? GetConnectedPeersHelper)
      .mapTo[Seq[PeerInfoResponse]].map(_.asJson).okJson()
  }

  def bannedList: Route = (path("banned") & get) {
    (dataHolder ? GetBannedPeersHelper).mapTo[Seq[(InetAddress, (BanReason, BanTime, BanType))]]
    .map(_.map(_.toString).asJson).okJson()
  }

  def connectPeer: Route = path("add") {
    post(entity(as[String]) { str =>
      complete {
        Try {
          val split = str.split(':')
          (split(0), split(1).toInt)
        } match {
          case Success((host, port)) =>
            dataHolder ! UserAddPeer(new InetSocketAddress(host, port))
            StatusCodes.OK
          case Failure(_) =>
            StatusCodes.BadRequest
        }
      }
    })
  }

  def removeFromBan: Route = path("remove") {
    post(entity(as[String]) { str =>
      complete {
        Try {
          val split = str.split(':')
          (split(0), split(1).toInt)
        } match {
          case Success((host, port)) =>
            dataHolder ! RemovePeerFromBanList(new InetSocketAddress(host, port))
            StatusCodes.OK
          case Failure(_) =>
            StatusCodes.BadRequest
        }
      }
    })
  }
}

object PeersApiRoute {

  case class PeerInfoResponse(address: String, name: Option[String], connectionType: Option[String])

  object PeerInfoResponse {

    def fromAddressAndInfo(address: InetSocketAddress, peerInfo: PeerInfo): PeerInfoResponse = PeerInfoResponse(
      address.toString,
      Some(peerInfo.connectedPeer.toString),
      Some(peerInfo.connectionType.toString)
    )
  }

  implicit val encodePeerInfoResponse: Encoder[PeerInfoResponse] = deriveEncoder
} 
Example 28
Source File: CompositeHttpService.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import encry.api.http.routes.SwaggerRoute
import encry.settings.RESTApiSettings

case class CompositeHttpService(system: ActorSystem,
                                routes: Seq[ApiRoute],
                                settings: RESTApiSettings,
                                swaggerConf: String) {

  implicit val actorSystem: ActorSystem = system

  val redirectToSwagger: Route = redirect("/swagger", StatusCodes.PermanentRedirect)

  @SuppressWarnings(Array("org.wartremover.warts.TraversableOps"))
  val compositeRoute: Route = routes.map(_.route).reduce(_ ~ _) ~
    path("swagger") { getFromResource("swagger-ui/index.html") } ~
    getFromResourceDirectory("swagger-ui") ~
    SwaggerRoute.routes ~
    redirectToSwagger
} 
Example 29
Source File: ApiError.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.api.http

import akka.http.scaladsl.model.{StatusCode, StatusCodes}
import akka.http.scaladsl.server.{Directives, Route}
import scala.language.implicitConversions

case class ApiError(statusCode: StatusCode, reason: String = "") {

  def apply(detail: String): Route = complete(detail)
  def defaultRoute: Route = complete()

  def complete(detail: String = ""): Route = {
    val nonEmptyReason = if (reason.isEmpty) statusCode.reason else reason
    val body = if (detail.isEmpty) nonEmptyReason else s"$nonEmptyReason $detail"
    Directives.complete(statusCode.intValue() -> body)
  }
}

object ApiError {
  def apply(s: String): Route = InternalError(s)
  def apply(e: Throwable): Route = InternalError(e.getMessage)
  def apply(causes: Seq[Throwable]): Route = InternalError(mkString(causes))
  def mkString(causes: Seq[Throwable]): String = causes.map(_.getMessage).mkString(", ")

  implicit def toRoute(error: ApiError): Route = error.defaultRoute

  object InternalError extends ApiError(StatusCodes.InternalServerError, "internal.error")
  object InvalidJson extends ApiError(StatusCodes.BadRequest, "invalid.json")
  object BadRequest extends ApiError(StatusCodes.BadRequest, "bad.request")
  object ApiKeyNotValid extends ApiError(StatusCodes.Forbidden, "invalid.api-key")
  object NotExists extends ApiError(StatusCodes.NotFound, "not-found")
} 
Example 30
Source File: Routes.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.ingest.modules

import akka.actor.ActorSystem
import akka.http.scaladsl.server.directives.RouteDirectives
import akka.http.scaladsl.server.{Route, RouteConcatenation}
import cats.effect.Sync
import hydra.common.config.ConfigSupport
import hydra.common.util.{ActorUtils, Futurable}
import hydra.ingest.app.AppConfig.AppConfig
import hydra.ingest.http._
import hydra.kafka.consumer.KafkaConsumerProxy
import hydra.kafka.endpoints.{BootstrapEndpoint, BootstrapEndpointV2, TopicMetadataEndpoint, TopicsEndpoint}
import hydra.kafka.util.KafkaUtils.TopicDetails

import scala.concurrent.ExecutionContext

final class Routes[F[_]: Sync: Futurable] private(programs: Programs[F], algebras: Algebras[F], cfg: AppConfig)
                                                 (implicit system: ActorSystem) extends RouteConcatenation with ConfigSupport {

  private implicit val ec: ExecutionContext = system.dispatcher
  private val bootstrapEndpointV2 = if (cfg.v2MetadataTopicConfig.createV2TopicsEnabled) {
    val topicDetails =
      TopicDetails(
        cfg.createTopicConfig.defaultNumPartions,
        cfg.createTopicConfig.defaultReplicationFactor
      )
    new BootstrapEndpointV2(programs.createTopic, topicDetails).route
  } else {
    RouteDirectives.reject
  }

  lazy val routes: F[Route] = Sync[F].delay {
    import ConfigSupport._

    //TODO: remove this lookup
    val consumerPath = applicationConfig
      .getStringOpt("actors.kafka.consumer_proxy.path")
      .getOrElse(
        s"/user/service/${ActorUtils.actorName(classOf[KafkaConsumerProxy])}"
      )

    val consumerProxy = system.actorSelection(consumerPath)

    new SchemasEndpoint().route ~
      new BootstrapEndpoint(system).route ~
      new TopicMetadataEndpoint(consumerProxy, algebras.metadata).route ~
      new IngestorRegistryEndpoint().route ~
      new IngestionWebSocketEndpoint().route ~
      new IngestionEndpoint(cfg.ingestConfig.alternateIngestEnabled,
                            programs.ingestionFlow,
                            programs.ingestionFlowV2,
                            cfg.ingestConfig.useOldIngestIfUAContains).route ~
      new TopicsEndpoint(consumerProxy)(system.dispatcher).route ~
      HealthEndpoint.route ~
      bootstrapEndpointV2
  }
}

object Routes {
  def make[F[_]: Sync: Futurable](programs: Programs[F], algebras: Algebras[F], config: AppConfig)
                           (implicit system: ActorSystem): F[Routes[F]] = Sync[F].delay(new Routes[F](programs, algebras, config))
} 
Example 31
Source File: IngestorRegistryEndpoint.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.ingest.http

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import hydra.common.config.ConfigSupport
import ConfigSupport._
import hydra.core.http.RouteSupport
import hydra.ingest.bootstrap.HydraIngestorRegistryClient
import hydra.ingest.services.IngestorRegistry.{FindAll, LookupResult}

import scala.concurrent.duration.{FiniteDuration, _}


class IngestorRegistryEndpoint()(implicit system:ActorSystem) extends RouteSupport
    with HydraIngestJsonSupport
    with ConfigSupport {

  private val registryLookupTimeout = applicationConfig
    .getDurationOpt("ingest.service-lookup.timeout")
    .getOrElse(5.seconds)

  lazy val registry = HydraIngestorRegistryClient(applicationConfig).registry

  private implicit val timeout = Timeout(registryLookupTimeout)

  override val route: Route =
    path("ingestors" ~ Slash.?) {
      get {
        onSuccess(registry ? FindAll) {
          case response: LookupResult => complete(response.ingestors)
        }
      }
    }
} 
Example 32
Source File: MockEndpoint.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.ingest.http.mock

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ExceptionHandler, Route}
import hydra.ingest.http.SchemasEndpoint
import io.confluent.kafka.schemaregistry.client.rest.exceptions.RestClientException

import scala.concurrent.{ExecutionContext, Future}

class MockEndpoint(
    implicit system: ActorSystem,
    implicit val e: ExecutionContext
) {

  def throwRestClientException(
      statusCode: Int,
      errorCode: Int,
      errorMessage: String
  ): Future[Any] = {
    throw new RestClientException(errorMessage, statusCode, errorCode)
  }

  val schemaRouteExceptionHandler: ExceptionHandler =
    new SchemasEndpoint().excptHandler

  def route: Route = {
    pathPrefix("throwRestClientException") {
      handleExceptions(schemaRouteExceptionHandler) {
        get {
          parameters('statusCode, 'errorCode, 'errorMessage) {
            (statusCode, errorCode, errorMessage) =>
              pathEndOrSingleSlash {
                onSuccess(
                  throwRestClientException(
                    statusCode.toInt,
                    errorCode.toInt,
                    errorMessage
                  )
                ) { _ => complete(OK) }
              }
          }
        }
      }
    }
  }
} 
Example 33
Source File: BootstrapEndpointV2.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.kafka.endpoints

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.megard.akka.http.cors.scaladsl.CorsDirectives.cors
import hydra.avro.registry.SchemaRegistry.IncompatibleSchemaException
import hydra.common.util.Futurable
import hydra.core.http.CorsSupport
import hydra.core.marshallers.GenericServiceResponse
import hydra.kafka.model.TopicMetadataV2Request
import hydra.kafka.model.TopicMetadataV2Request.Subject
import hydra.kafka.programs.CreateTopicProgram
import hydra.kafka.serializers.TopicMetadataV2Parser
import hydra.kafka.util.KafkaUtils.TopicDetails
import org.apache.avro.SchemaParseException

import scala.util.{Failure, Success}

final class BootstrapEndpointV2[F[_]: Futurable](
    createTopicProgram: CreateTopicProgram[F],
    defaultTopicDetails: TopicDetails,
) extends CorsSupport {

  import TopicMetadataV2Parser._

  val route: Route = cors(settings) {
    pathPrefix("v2" / "topics" / Segment) { topicName =>
      pathEndOrSingleSlash {
        put {
          entity(as[TopicMetadataV2Request]) { t =>
            Subject.createValidated(topicName) match {
              case Some(validatedTopic) =>
                onComplete(
                  Futurable[F].unsafeToFuture(createTopicProgram
                    .createTopic(validatedTopic, t, defaultTopicDetails))
                ) {
                  case Success(_) => complete(StatusCodes.OK)
                  case Failure(IncompatibleSchemaException(m)) => complete(StatusCodes.BadRequest, m)
                  case Failure(e) => complete(StatusCodes.InternalServerError, e)
                }
              case None =>
                complete(StatusCodes.BadRequest, Subject.invalidFormat)
            }
          }
        }
      }
    }
  }

} 
Example 34
Source File: BootstrapEndpoint.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.kafka.endpoints

import akka.actor._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._
import hydra.common.logging.LoggingAdapter
import hydra.core.http.{CorsSupport, HydraDirectives, RouteSupport}
import hydra.core.marshallers.TopicMetadataRequest
import hydra.kafka.model.TopicMetadataAdapter
import hydra.kafka.services.TopicBootstrapActor._

import scala.concurrent.duration._
import scala.util.{Failure, Success}

class BootstrapEndpoint(override val system:ActorSystem) extends RouteSupport
  with LoggingAdapter
  with TopicMetadataAdapter
  with HydraDirectives
  with CorsSupport
  with BootstrapEndpointActors {

  private implicit val timeout = Timeout(10.seconds)

  override val route: Route = cors(settings) {
    pathPrefix("streams") {
      pathEndOrSingleSlash {
        post {
          requestEntityPresent {
            entity(as[TopicMetadataRequest]) { topicMetadataRequest =>
              onComplete(
                bootstrapActor ? InitiateTopicBootstrap(topicMetadataRequest)
              ) {
                case Success(message) =>
                  message match {

                    case BootstrapSuccess(metadata) =>
                      complete(StatusCodes.OK, toResource(metadata))

                    case BootstrapFailure(reasons) =>
                      complete(StatusCodes.BadRequest, reasons)

                    case e: Exception =>
                      log.error("Unexpected error in TopicBootstrapActor", e)
                      complete(StatusCodes.InternalServerError, e.getMessage)
                  }

                case Failure(ex) =>
                  log.error("Unexpected error in BootstrapEndpoint", ex)
                  complete(StatusCodes.InternalServerError, ex.getMessage)
              }
            }
          }
        }
      } ~ get {
        pathEndOrSingleSlash(getAllStreams(None)) ~
          path(Segment)(subject => getAllStreams(Some(subject)))
      }
    }
  }

  private def getAllStreams(subject: Option[String]): Route = {
    onSuccess(bootstrapActor ? GetStreams(subject)) {
      case GetStreamsResponse(metadata) =>
        complete(StatusCodes.OK, metadata.map(toResource))
      case Failure(ex) =>
        throw ex
      case x =>
        log.error("Unexpected error in BootstrapEndpoint", x)
        complete(StatusCodes.InternalServerError, "Unknown error")
    }
  }
} 
Example 35
Source File: TestHttpProxy.scala    From akka-stream-sqs   with Apache License 2.0 5 votes vote down vote up
package me.snov.akka.sqs

import akka.actor.{ActorSystem, Terminated}
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.{RequestContext, Route}
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}

import scala.concurrent.{Await, Future}
import scala.concurrent.duration._

class TestHttpProxy(
                     interface: String = "localhost",
                     port: Int,
                     remoteHost: String = "localhost",
                     remotePort: Int = 9324
                   ) {

  implicit var system: ActorSystem = createActorSystem()

  private def createActorSystem() = ActorSystem("test-http-server")

  def start(): Unit = {
    implicit val materializer: ActorMaterializer = ActorMaterializer()
    implicit val executionContext = system.dispatcher

    val proxy = Route { context: RequestContext =>
      context.log.debug("Opening connection to %s:%d".format(remoteHost, remotePort))
      Source.single(context.request)
        .via(Http(system).outgoingConnection(remoteHost, remotePort))
        .runWith(Sink.head)
        .flatMap(context.complete(_))
    }

    Http().bindAndHandle(handler = proxy, interface = interface, port = port)
  }

  def stop(): Unit = {
    Await.ready(system.terminate(), 1.second)
  }

  def asyncStartAfter(d: FiniteDuration) = {
    system = createActorSystem()
    system.scheduler.scheduleOnce(d, new Runnable {
      override def run(): Unit = start()
    })(system.dispatcher)
  }
} 
Example 36
Source File: HealthService.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.api

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ Route, StandardRoute }
import com.ing.wbaa.rokku.proxy.data.HealthCheck.{ RGWListBuckets, S3ListBucket }
import com.ing.wbaa.rokku.proxy.handler.radosgw.RadosGatewayHandler
import com.ing.wbaa.rokku.proxy.provider.aws.S3Client
import com.typesafe.scalalogging.LazyLogging
import java.util.concurrent.ConcurrentHashMap

import scala.collection.JavaConverters._
import scala.collection.mutable
import scala.concurrent.{ ExecutionContext, Future }
import scala.util.{ Failure, Success, Try }

object HealthService {
  private def timestamp: Long = System.currentTimeMillis()

  private val statusMap = new ConcurrentHashMap[Long, StandardRoute]()

  private def clearStatus(): Unit = statusMap.clear()

  private def addStatus(probeResult: StandardRoute): StandardRoute = statusMap.put(timestamp, probeResult)

  private def getCurrentStatusMap: Future[mutable.Map[Long, StandardRoute]] = Future.successful(statusMap.asScala)

  private def getRouteStatus(implicit ec: ExecutionContext): Future[Option[StandardRoute]] = getCurrentStatusMap.map(_.headOption.map { case (_, r) => r })

}

trait HealthService extends RadosGatewayHandler with S3Client with LazyLogging {

  protected[this] implicit def executionContext: ExecutionContext

  import HealthService.{ addStatus, getCurrentStatusMap, clearStatus, getRouteStatus, timestamp }

  private lazy val interval = storageS3Settings.hcInterval

  private def updateStatus: Future[StandardRoute] = Future {
    clearStatus()
    storageS3Settings.hcMethod match {
      case RGWListBuckets => addStatus(execProbe(listAllBuckets _))
      case S3ListBucket   => addStatus(execProbe(listBucket _))
    }
  }
  private def updateStatusAndGet: Future[Option[StandardRoute]] =
    for {
      _ <- updateStatus
      s <- getRouteStatus
    } yield s

  def getStatus(currentTime: Long): Future[Option[StandardRoute]] =
    getCurrentStatusMap.flatMap(_ match {
      case m if m.isEmpty =>
        logger.debug("Status cache empty, running probe")
        updateStatusAndGet
      case m => m.keys.map {
        case entryTime if (entryTime + interval) < currentTime =>
          logger.debug("Status entry expired, renewing")
          updateStatusAndGet
        case _ =>
          logger.debug("Serving status from cache")
          Future.successful(m.map { case (_, r) => r }.headOption)
      }.head
    })

  private def execProbe[A](p: () => A): StandardRoute =
    Try {
      p()
    } match {
      case Success(_)  => complete("pong")
      case Failure(ex) => complete(StatusCodes.InternalServerError -> s"storage not available - $ex")
    }

  final val healthRoute: Route =
    path("ping") {
      get {
        onComplete(getStatus(timestamp)) {
          case Success(opt) => opt.getOrElse(complete(StatusCodes.InternalServerError -> "Failed to read status cache"))
          case Failure(e)   => complete(StatusCodes.InternalServerError -> "Failed to read status cache " + e.getMessage)
        }
      }
    }
} 
Example 37
Source File: ProxyServiceWithListAllBuckets.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.api

import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.ing.wbaa.rokku.proxy.data.{ Read, RequestId, S3Request, User }

import scala.xml.NodeSeq


trait ProxyServiceWithListAllBuckets extends ProxyService with ScalaXmlSupport {

  protected[this] def listAllBuckets: Seq[String]

  override protected[this] def processAuthorizedRequest(httpRequest: HttpRequest, s3Request: S3Request, userSTS: User)(implicit id: RequestId): Route = {
    s3Request match {
      //only when list buckets is requested we show all buckets
      case S3Request(_, None, None, accessType, _, _, _) if accessType.isInstanceOf[Read] =>
        complete(getListAllMyBucketsXml())
      case _ => super.processAuthorizedRequest(httpRequest, s3Request, userSTS)
    }
  }

  private def getListAllMyBucketsXml(user: String = "npa", createDate: String = "2018-01-01T00:00:00.000Z"): NodeSeq = {
    <ListAllMyBucketsResult>
      <Owner>
        <ID>{ user }</ID>
        <DisplayName>{ user }</DisplayName>
      </Owner>
      <Buckets>
        { for (bucketName <- listAllBuckets) yield <Bucket><Name>{ bucketName }</Name><CreationDate>{ createDate }</CreationDate></Bucket> }
      </Buckets>
    </ListAllMyBucketsResult>
  }
} 
Example 38
Source File: DarwinService.scala    From darwin   with Apache License 2.0 5 votes vote down vote up
package it.agilelab.darwin.server.rest

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.directives.DebuggingDirectives
import akka.http.scaladsl.server.{Directives, Route}
import akka.stream.ActorMaterializer
import akka.stream.Attributes.LogLevels
import it.agilelab.darwin.manager.AvroSchemaManager
import org.apache.avro.Schema


trait DarwinService extends Service with Directives with DebuggingDirectives with JsonSupport {

  val manager: AvroSchemaManager

  override def route: Route = logRequestResult(("darwin", LogLevels.Debug)) {
    get {
      path("schemas" / LongNumber.?) {
        case Some(id) => manager.getSchema(id) match {
          case Some(schema) => complete(schema)
          case None => complete {
            HttpResponse(StatusCodes.NotFound)
          }
        }
        case None => complete(manager.getAll)
      }
    } ~ post {
      path("schemas" / PathEnd) {
        entity(as[Seq[Schema]]) { schemas =>
          complete {
            manager.registerAll(schemas).map(_._1)
          }
        }
      }
    }
  }
}


object DarwinService {
  def apply(asm: AvroSchemaManager)(implicit s: ActorSystem, m: ActorMaterializer): DarwinService = new DarwinService {
    override implicit val materializer: ActorMaterializer = m
    override implicit val system: ActorSystem = s
    override val manager: AvroSchemaManager = asm
  }
} 
Example 39
Source File: CachingSpec.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play.api.libs.ws.ahc.cache

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.server.Route
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
import org.specs2.specification.AfterAll
import play.AkkaServerProvider
import play.api.libs.ws.ahc._
import play.shaded.ahc.org.asynchttpclient._

import scala.concurrent.Future

class CachingSpec(implicit val executionEnv: ExecutionEnv)
    extends Specification
    with AkkaServerProvider
    with AfterAll
    with FutureMatchers
    with Mockito {

  val asyncHttpClient: AsyncHttpClient = {
    val config                           = AhcWSClientConfigFactory.forClientConfig()
    val ahcConfig: AsyncHttpClientConfig = new AhcConfigBuilder(config).build()
    new DefaultAsyncHttpClient(ahcConfig)
  }

  override val routes: Route = {
    import akka.http.scaladsl.server.Directives._
    path("hello") {
      respondWithHeader(RawHeader("Cache-Control", "public")) {
        val httpEntity = HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>")
        complete(httpEntity)
      }
    }
  }

  override def afterAll = {
    super.afterAll()
    asyncHttpClient.close()
  }

  "GET" should {

    "work once" in {
      val cache = mock[Cache]
      cache.get(any[EffectiveURIKey]()).returns(Future.successful(None))

      val cachingAsyncHttpClient = new CachingAsyncHttpClient(asyncHttpClient, new AhcHttpCache(cache))
      val ws                     = new StandaloneAhcWSClient(cachingAsyncHttpClient)

      ws.url(s"http://localhost:$testServerPort/hello")
        .get()
        .map { response =>
          response.body must be_==("<h1>Say hello to akka-http</h1>")
        }
        .await

      there.was(one(cache).get(EffectiveURIKey("GET", new java.net.URI(s"http://localhost:$testServerPort/hello"))))
    }
  }
} 
Example 40
Source File: AhcWSClientSpec.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play.libs.ws.ahc

import akka.http.scaladsl.server.Route
import akka.stream.javadsl.Sink
import akka.util.ByteString
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mutable.Specification
import play.AkkaServerProvider
import play.libs.ws._

import scala.compat.java8.FutureConverters._
import scala.concurrent.Future
import scala.concurrent.duration._

class AhcWSClientSpec(implicit val executionEnv: ExecutionEnv)
    extends Specification
    with AkkaServerProvider
    with StandaloneWSClientSupport
    with FutureMatchers
    with XMLBodyWritables
    with XMLBodyReadables {

  override val routes: Route = {
    import akka.http.scaladsl.server.Directives._
    get {
      complete("<h1>Say hello to akka-http</h1>")
    } ~
      post {
        entity(as[String]) { echo =>
          complete(echo)
        }
      }
  }

  "play.libs.ws.ahc.StandaloneAhcWSClient" should {

    "get successfully" in withClient() { client =>
      def someOtherMethod(string: String) = {
        new InMemoryBodyWritable(akka.util.ByteString.fromString(string), "text/plain")
      }
      toScala(client.url(s"http://localhost:$testServerPort").post(someOtherMethod("hello world")))
        .map(response => response.getBody() must be_==("hello world"))
        .await(retries = 0, timeout = 5.seconds)
    }

    "source successfully" in withClient() { client =>
      val future = toScala(client.url(s"http://localhost:$testServerPort").stream())
      val result: Future[ByteString] = future.flatMap { response: StandaloneWSResponse =>
        toScala(response.getBodyAsSource.runWith(Sink.head[ByteString](), materializer))
      }
      val expected: ByteString = ByteString.fromString("<h1>Say hello to akka-http</h1>")
      result must be_==(expected).await(retries = 0, timeout = 5.seconds)
    }

    "round trip XML successfully" in withClient() { client =>
      val document = XML.fromString("""<?xml version="1.0" encoding='UTF-8'?>
                                      |<note>
                                      |  <from>hello</from>
                                      |  <to>world</to>
                                      |</note>""".stripMargin)
      document.normalizeDocument()

      toScala {
        client.url(s"http://localhost:$testServerPort").post(body(document))
      }.map { response =>
          import javax.xml.parsers.DocumentBuilderFactory
          val dbf = DocumentBuilderFactory.newInstance
          dbf.setNamespaceAware(true)
          dbf.setCoalescing(true)
          dbf.setIgnoringElementContentWhitespace(true)
          dbf.setIgnoringComments(true)
          dbf.newDocumentBuilder

          val responseXml = response.getBody(xml())
          responseXml.normalizeDocument()

          (responseXml.isEqualNode(document) must beTrue).and {
            response.getUri must beEqualTo(new java.net.URI(s"http://localhost:$testServerPort"))
          }
        }
        .await(retries = 0, timeout = 5.seconds)
    }
  }
} 
Example 41
Source File: AkkaServerProvider.scala    From play-ws   with Apache License 2.0 5 votes vote down vote up
package play

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import org.specs2.concurrent.ExecutionEnv
import org.specs2.specification.BeforeAfterAll

import scala.concurrent.duration._
import scala.concurrent.Await
import scala.concurrent.Future
import akka.stream.Materializer

trait AkkaServerProvider extends BeforeAfterAll {

  
  def executionEnv: ExecutionEnv

  var testServerPort: Int            = _
  val defaultTimeout: FiniteDuration = 5.seconds

  // Create Akka system for thread and streaming management
  implicit val system       = ActorSystem()
  implicit val materializer = Materializer.matFromSystem

  lazy val futureServer: Future[Http.ServerBinding] = {
    // Using 0 (zero) means that a random free port will be used.
    // So our tests can run in parallel and won't mess with each other.
    Http().bindAndHandle(routes, "localhost", 0)
  }

  override def beforeAll(): Unit = {
    val portFuture = futureServer.map(_.localAddress.getPort)(executionEnv.executionContext)
    portFuture.foreach(port => testServerPort = port)(executionEnv.executionContext)
    Await.ready(portFuture, defaultTimeout)
  }

  override def afterAll(): Unit = {
    futureServer.foreach(_.unbind())(executionEnv.executionContext)
    val terminate = system.terminate()
    Await.ready(terminate, defaultTimeout)
  }
} 
Example 42
Source File: HttpRouter.scala    From JustinDB   with Apache License 2.0 5 votes vote down vote up
package justin.httpapi

import java.util.UUID

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import justin.db.Data
import justin.db.client.{ActorRefStorageNodeClient, GetValueResponse, WriteValueResponse}
import justin.db.replica.{R, W}
import justin.db.storage.Base64
import justin.db.versioning.NodeIdVectorClockBase64
import justin.httpapi.JustinDirectives._
import justin.httpapi.Unmarshallers.UUIDUnmarshaller
import spray.json.DefaultJsonProtocol._
import spray.json.RootJsonFormat

import scala.concurrent.ExecutionContext
import scala.util.{Failure, Success}

object HttpRouter {
  import Unmarshallers.UuidFormat

  case class Result(value: String)
  implicit val valueFormat: RootJsonFormat[Result] = jsonFormat1(Result)

  case class ConflictedData(id: String, value: String, vclock: Base64)
  implicit val conflictedDataFormat: RootJsonFormat[ConflictedData] = jsonFormat3(ConflictedData)

  case class PutValue(id: UUID, value: String, w: Int)
  implicit val putValueFormat: RootJsonFormat[PutValue] = jsonFormat3(PutValue)
}

class HttpRouter(client: ActorRefStorageNodeClient)(implicit ec: ExecutionContext) {
  import HttpRouter._

  private[this] def transformConflictedData(data: Data) = {
    val vcBase64 = new NodeIdVectorClockBase64().encode(data.vclock).get
    ConflictedData(data.id.toString, data.value, vcBase64)
  }

  def routes: Route = withVectorClockHeader { vClockHeader =>
    {
      (get & path("get") & pathEndOrSingleSlash & parameters(('id.as(UUIDUnmarshaller), 'r.as[Int]))) { (uuid, r) =>
        onComplete(client.get(uuid, R(r))) {
          case Success(GetValueResponse.Found(data))     => respondWithHeader(VectorClockHeader(data.vclock)) { complete(OK -> Result(data.value)) }
          case Success(GetValueResponse.Conflicts(data)) => complete(MultipleChoices -> data.map(transformConflictedData))
          case Success(GetValueResponse.NotFound(id))    => complete(NotFound -> Result(s"Couldn't found value with id ${id.toString}"))
          case Success(GetValueResponse.Failure(err))    => complete(BadRequest -> Result(err))
          case Failure(ex)                               => complete(InternalServerError -> Result(ex.getMessage))
        }
      }
    } ~
    (post & path("put") & pathEndOrSingleSlash & entity(as[PutValue])) { putValue =>
      complete {
        client.write(Data(putValue.id, putValue.value, vClockHeader.vectorClock), W(putValue.w)).map[ToResponseMarshallable] {
          case WriteValueResponse.Success(id)  => NoContent
          case WriteValueResponse.Conflict     => MultipleChoices -> Result("Multiple Choices")
          case WriteValueResponse.Failure(err) => BadRequest      -> Result(err)
        }
      }
    }
  }
} 
Example 43
Source File: ProducerCommands.scala    From reactive-kafka-microservice-template   with Apache License 2.0 5 votes vote down vote up
package com.omearac.http.routes

import akka.actor.ActorRef
import akka.event.LoggingAdapter
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import com.omearac.producers.DataProducer.PublishMessages
import com.omearac.shared.EventMessages.MessagesPublished

import scala.concurrent.duration._




trait ProducerCommands {
    def log: LoggingAdapter
    def dataProducer: ActorRef

    val producerHttpCommands: Route = pathPrefix("data_producer"){
        implicit val timeout = Timeout(10 seconds)
        path("produce" / IntNumber) {
            {numOfMessagesToProduce =>
                get {
                    onSuccess(dataProducer ? PublishMessages(numOfMessagesToProduce)) {
                        case MessagesPublished(numberOfMessages) => complete(StatusCodes.OK,  numberOfMessages + " messages Produced as Ordered, Boss!")
                        case _ => complete(StatusCodes.InternalServerError)
                    }
                }
            }
        }
    }
} 
Example 44
Source File: ActionsApiWithoutDbPollingTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import java.time.Instant

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.core.controller.WhiskActionsApi
import org.apache.openwhisk.core.controller.actions.ControllerActivationConfig
import org.apache.openwhisk.core.database.UserContext
import org.apache.openwhisk.core.entity._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import spray.json.DefaultJsonProtocol._
import spray.json._

import scala.concurrent.duration.DurationInt


  behavior of "Actions API without DB Polling"

  val creds = WhiskAuthHelpers.newIdentity()
  val context = UserContext(creds)
  val namespace = EntityPath(creds.subject.asString)
  val collectionPath = s"/${EntityPath.DEFAULT}/${collection.path}"

  def aname() = MakeName.next("action_tests")

  val actionLimit = Exec.sizeLimit
  val parametersLimit = Parameters.sizeLimit

  override val controllerActivationConfig = ControllerActivationConfig(false, 2.seconds)

  it should "invoke a blocking action which is converted to a non-blocking due to delayed active ack" in {
    implicit val tid = transid()
    val action = WhiskAction(
      namespace,
      aname(),
      jsDefault("??"),
      limits = ActionLimits(
        TimeLimit(controllerActivationConfig.maxWaitForBlockingActivation - 1.second),
        MemoryLimit(),
        LogLimit()))

    put(entityStore, action)
    val start = Instant.now
    Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
      // status should be accepted because there is no active ack response and
      // db polling will fail since there is no record of the activation
      // as a result, the api handler will convert this to a non-blocking request
      status should be(Accepted)
      val duration = Instant.now.toEpochMilli - start.toEpochMilli
      val response = responseAs[JsObject]

      response.fields.size shouldBe 1
      response.fields("activationId") should not be None
      headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String]))

      // all blocking requests wait up to the specified blocking timeout regadless of the action time limit
      duration should be >= controllerActivationConfig.maxWaitForBlockingActivation.toMillis
    }
  }

  it should "invoke a blocking action which completes with an activation id only" in {
    implicit val tid = transid()
    val action = WhiskAction(namespace, aname(), jsDefault("??"))
    put(entityStore, action)

    try {
      // do not store the activation in the db, instead register it as the response to generate on active ack
      loadBalancer.whiskActivationStub = Some((1.milliseconds, Left(activationIdFactory.make())))

      val start = Instant.now
      Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
        // status should be accepted because the test is simulating a response which only has
        // an activation id response from the invoker; unlike the previous test, here the invoker
        // does respond to complete the api handler's waiting promise
        status should be(Accepted)
        val duration = Instant.now.toEpochMilli - start.toEpochMilli
        val response = responseAs[JsObject]

        response.fields.size shouldBe 1
        response.fields("activationId") should not be None
        headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String]))
        duration should be <= 1.second.toMillis
      }
    } finally {
      loadBalancer.whiskActivationStub = None
    }
  }

} 
Example 45
Source File: NamespacesApiTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

import akka.http.scaladsl.model.StatusCodes.OK
import akka.http.scaladsl.model.StatusCodes.NotFound
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
import akka.http.scaladsl.server.Route

import spray.json.DefaultJsonProtocol._

import org.apache.openwhisk.core.controller.WhiskNamespacesApi
import org.apache.openwhisk.core.entity.EntityPath


  behavior of "Namespaces API"

  val collectionPath = s"/${collection.path}"
  val creds = WhiskAuthHelpers.newIdentity()
  val namespace = EntityPath(creds.subject.asString)

  it should "list namespaces for subject" in {
    implicit val tid = transid()
    Seq("", "/").foreach { p =>
      Get(collectionPath + p) ~> Route.seal(routes(creds)) ~> check {
        status should be(OK)
        val ns = responseAs[List[EntityPath]]
        ns should be(List(EntityPath(creds.subject.asString)))
      }
    }
  }

  it should "reject request for unsupported method" in {
    implicit val tid = transid()
    Seq(Get, Put, Post, Delete).foreach { m =>
      m(s"$collectionPath/${creds.subject}") ~> Route.seal(routes(creds)) ~> check {
        status should be(NotFound)
      }
    }
  }
} 
Example 46
Source File: RespondWithHeadersTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

import akka.http.scaladsl.model.StatusCodes.NotFound
import akka.http.scaladsl.model.StatusCodes.OK
import akka.http.scaladsl.server.Route

import org.apache.openwhisk.core.controller.RespondWithHeaders


@RunWith(classOf[JUnitRunner])
class RespondWithHeadersTests extends ControllerTestCommon with RespondWithHeaders {

  behavior of "General API"

  val routes = {
    pathPrefix("api" / "v1") {
      sendCorsHeaders {
        path("one") {
          complete(OK)
        } ~ path("two") {
          complete(OK)
        } ~ options {
          complete(OK)
        } ~ reject
      }
    } ~ pathPrefix("other") {
      complete(OK)
    }
  }

  it should "respond to options" in {
    Options("/api/v1") ~> Route.seal(routes) ~> check {
      headers should contain allOf (allowOrigin, allowHeaders)
    }
  }

  it should "respond to options on every route under /api/v1" in {
    Options("/api/v1/one") ~> Route.seal(routes) ~> check {
      headers should contain allOf (allowOrigin, allowHeaders)
    }
    Options("/api/v1/two") ~> Route.seal(routes) ~> check {
      headers should contain allOf (allowOrigin, allowHeaders)
    }
  }

  it should "respond to options even on bogus routes under /api/v1" in {
    Options("/api/v1/bogus") ~> Route.seal(routes) ~> check {
      headers should contain allOf (allowOrigin, allowHeaders)
    }
  }

  it should "not respond to options on routes before /api/v1" in {
    Options("/api") ~> Route.seal(routes) ~> check {
      status shouldBe NotFound
    }
  }

} 
Example 47
Source File: LimitsApiTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import akka.http.scaladsl.model.StatusCodes.{BadRequest, MethodNotAllowed, OK}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.core.controller.WhiskLimitsApi
import org.apache.openwhisk.core.entity.{EntityPath, UserLimits}


  behavior of "Limits API"

  // test namespace limit configurations
  val testInvokesPerMinute = 100
  val testConcurrent = 200
  val testFiresPerMinute = 300
  val testAllowedKinds = Set("java:8")
  val testStoreActivations = false

  val creds = WhiskAuthHelpers.newIdentity()
  val credsWithSetLimits = WhiskAuthHelpers
    .newIdentity()
    .copy(
      limits = UserLimits(
        Some(testInvokesPerMinute),
        Some(testConcurrent),
        Some(testFiresPerMinute),
        Some(testAllowedKinds),
        Some(testStoreActivations)))
  val namespace = EntityPath(creds.subject.asString)
  val collectionPath = s"/${EntityPath.DEFAULT}/${collection.path}"

  //// GET /limits
  it should "list default system limits if no namespace limits are set" in {
    implicit val tid = transid()
    Seq("", "/").foreach { p =>
      Get(collectionPath + p) ~> Route.seal(routes(creds)) ~> check {
        status should be(OK)
        responseAs[UserLimits].invocationsPerMinute shouldBe Some(whiskConfig.actionInvokePerMinuteLimit.toInt)
        responseAs[UserLimits].concurrentInvocations shouldBe Some(whiskConfig.actionInvokeConcurrentLimit.toInt)
        responseAs[UserLimits].firesPerMinute shouldBe Some(whiskConfig.triggerFirePerMinuteLimit.toInt)
        responseAs[UserLimits].allowedKinds shouldBe None
        responseAs[UserLimits].storeActivations shouldBe None
      }
    }
  }

  it should "list set limits if limits have been set for the namespace" in {
    implicit val tid = transid()
    Seq("", "/").foreach { p =>
      Get(collectionPath + p) ~> Route.seal(routes(credsWithSetLimits)) ~> check {
        status should be(OK)
        responseAs[UserLimits].invocationsPerMinute shouldBe Some(testInvokesPerMinute)
        responseAs[UserLimits].concurrentInvocations shouldBe Some(testConcurrent)
        responseAs[UserLimits].firesPerMinute shouldBe Some(testFiresPerMinute)
        responseAs[UserLimits].allowedKinds shouldBe Some(testAllowedKinds)
        responseAs[UserLimits].storeActivations shouldBe Some(testStoreActivations)
      }
    }
  }

  it should "reject requests for unsupported methods" in {
    implicit val tid = transid()
    Seq(Put, Post, Delete).foreach { m =>
      m(collectionPath) ~> Route.seal(routes(creds)) ~> check {
        status should be(MethodNotAllowed)
      }
    }
  }

  it should "reject all methods for entity level request" in {
    implicit val tid = transid()
    Seq(Put, Post, Delete).foreach { m =>
      m(s"$collectionPath/limitsEntity") ~> Route.seal(routes(creds)) ~> check {
        status should be(MethodNotAllowed)
      }
    }

    Seq(Get).foreach { m =>
      m(s"$collectionPath/limitsEntity") ~> Route.seal(routes(creds)) ~> check {
        status should be(BadRequest)
      }
    }
  }
} 
Example 48
Source File: ControllerRoutesTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.common.AkkaLogging
import org.apache.openwhisk.core.controller.Controller
import org.apache.openwhisk.core.entity.ExecManifest.Runtimes
import org.junit.runner.RunWith
import org.scalatest.BeforeAndAfterEach
import org.scalatest.junit.JUnitRunner
import system.rest.RestUtil
import spray.json._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._



@RunWith(classOf[JUnitRunner])
class ControllerRoutesTests extends ControllerTestCommon with BeforeAndAfterEach with RestUtil {

  implicit val logger = new AkkaLogging(akka.event.Logging.getLogger(actorSystem, this))

  behavior of "Controller"

  it should "return unhealthy invokers status" in {

    configureBuildInfo()

    val controller =
      new Controller(instance, Runtimes(Set.empty, Set.empty, None), whiskConfig, system, materializer, logger)
    Get("/invokers/ready") ~> Route.seal(controller.internalInvokerHealth) ~> check {
      status shouldBe InternalServerError
      responseAs[JsObject].fields("unhealthy") shouldBe JsString("0/0")
    }
  }

  it should "return ready state true when healthy == total invokers" in {

    val res = Controller.readyState(5, 5, 1.0)
    res shouldBe true
  }

  it should "return ready state false when 0 invokers" in {

    val res = Controller.readyState(0, 0, 0.5)
    res shouldBe false
  }

  it should "return ready state false when threshold < (healthy / total)" in {

    val res = Controller.readyState(7, 3, 0.5)
    res shouldBe false
  }

  private def configureBuildInfo(): Unit = {
    System.setProperty("whisk.info.build-no", "")
    System.setProperty("whisk.info.date", "")
  }

} 
Example 49
Source File: SwaggerRoutesTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import org.junit.runner.RunWith
import org.scalatest.BeforeAndAfterEach
import org.scalatest.junit.JUnitRunner

import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.model.Uri

import spray.json._
import spray.json.DefaultJsonProtocol._

import org.apache.openwhisk.core.controller.SwaggerDocs



@RunWith(classOf[JUnitRunner])
class SwaggerRoutesTests extends ControllerTestCommon with BeforeAndAfterEach {

  behavior of "Swagger routes"

  it should "server docs" in {
    implicit val tid = transid()
    val swagger = new SwaggerDocs(Uri.Path.Empty, "infoswagger.json")
    Get("/docs") ~> Route.seal(swagger.swaggerRoutes) ~> check {
      status shouldBe PermanentRedirect
      header("location").get.value shouldBe "docs/index.html?url=/api-docs"
    }

    Get("/api-docs") ~> Route.seal(swagger.swaggerRoutes) ~> check {
      status shouldBe OK
      responseAs[JsObject].fields("swagger") shouldBe JsString("2.0")
    }
  }
} 
Example 50
Source File: ActionsApiWithDbPollingTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import java.time.Instant

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.core.controller.WhiskActionsApi
import org.apache.openwhisk.core.controller.actions.ControllerActivationConfig
import org.apache.openwhisk.core.database.UserContext
import org.apache.openwhisk.core.entity._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import spray.json.DefaultJsonProtocol._
import spray.json._

import scala.concurrent.duration.DurationInt


  behavior of "Actions API with DB Polling"

  val creds = WhiskAuthHelpers.newIdentity()
  val context = UserContext(creds)
  val namespace = EntityPath(creds.subject.asString)
  val collectionPath = s"/${EntityPath.DEFAULT}/${collection.path}"

  def aname() = MakeName.next("action_tests")

  val actionLimit = Exec.sizeLimit
  val parametersLimit = Parameters.sizeLimit

  override val controllerActivationConfig = ControllerActivationConfig(true, 60.seconds)

  it should "invoke a blocking action and retrieve result via db polling" in {
    implicit val tid = transid()
    val action = WhiskAction(namespace, aname(), jsDefault("??"))
    val activation = WhiskActivation(
      action.namespace,
      action.name,
      creds.subject,
      activationIdFactory.make(),
      start = Instant.now,
      end = Instant.now,
      response = ActivationResponse.success(Some(JsObject("test" -> "yes".toJson))),
      logs = ActivationLogs(Vector("first line", "second line")))
    put(entityStore, action)
    // storing the activation in the db will allow the db polling to retrieve it
    // the test harness makes sure the activation id observed by the test matches
    // the one generated by the api handler
    storeActivation(activation, false, false, context)
    try {
      Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
        status should be(OK)
        val response = responseAs[JsObject]
        response should be(activation.withoutLogs.toExtendedJson())
      }

      // repeat invoke, get only result back
      Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> Route.seal(routes(creds)) ~> check {
        status should be(OK)
        val response = responseAs[JsObject]
        response should be(activation.resultAsJson)
        headers should contain(RawHeader(ActivationIdHeader, activation.activationId.asString))
      }
    } finally {
      deleteActivation(ActivationId(activation.docid.asString), context)
    }
  }

  it should "invoke a blocking action and return error response when activation fails" in {
    implicit val tid = transid()
    val action = WhiskAction(namespace, aname(), jsDefault("??"))
    val activation = WhiskActivation(
      action.namespace,
      action.name,
      creds.subject,
      activationIdFactory.make(),
      start = Instant.now,
      end = Instant.now,
      response = ActivationResponse.whiskError("test"))
    put(entityStore, action)
    // storing the activation in the db will allow the db polling to retrieve it
    // the test harness makes sure the activation id observed by the test matches
    // the one generated by the api handler
    storeActivation(activation, false, false, context)
    try {
      Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
        status should be(InternalServerError)
        val response = responseAs[JsObject]
        response should be(activation.withoutLogs.toExtendedJson())
        headers should contain(RawHeader(ActivationIdHeader, response.fields("activationId").convertTo[String]))
      }
    } finally {
      deleteActivation(ActivationId(activation.docid.asString), context)
    }
  }
} 
Example 51
Source File: KafkaMetrics.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.connector.kafka

import akka.http.scaladsl.server.{Directives, Route}
import org.apache.kafka.common.{Metric, MetricName => JMetricName}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json._
import spray.json.DefaultJsonProtocol._

import scala.collection.JavaConverters._
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Success, Try}

trait KafkaMetricsProvider {
  def metrics(): Future[Map[JMetricName, Metric]]
}


object KafkaMetricRoute extends Directives {
  def apply(provider: KafkaMetricsProvider)(implicit ec: ExecutionContext): Route = {
    path("metrics" / "kafka") {
      val metrics = provider.metrics().map(m => KafkaMetrics.toJson(m))
      complete(metrics)
    }
  }
} 
Example 52
Source File: Prometheus.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.common
import java.nio.charset.StandardCharsets.UTF_8

import akka.http.scaladsl.model.{ContentType, HttpCharsets, HttpEntity, MediaType}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import kamon.Kamon
import kamon.prometheus.PrometheusReporter

class KamonPrometheus extends AutoCloseable {
  private val reporter = new PrometheusReporter
  private val v4: ContentType = ContentType.apply(
    MediaType.textWithFixedCharset("plain", HttpCharsets.`UTF-8`).withParams(Map("version" -> "0.0.4")))
  Kamon.registerModule("prometheus", reporter)

  def route: Route = path("metrics") {
    get {
      encodeResponse {
        complete(getReport())
      }
    }
  }

  private def getReport() = HttpEntity(v4, reporter.scrapeData().getBytes(UTF_8))

  override def close(): Unit = reporter.stop()
}

object MetricsRoute {
  private val impl =
    if (TransactionId.metricsKamon && TransactionId.metricConfig.prometheusEnabled) Some(new KamonPrometheus)
    else None

  def apply(): Route = impl.map(_.route).getOrElse(reject)
} 
Example 53
Source File: PrometheusEventsApi.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.monitoring.metrics

import akka.http.scaladsl.model.StatusCodes.ServiceUnavailable
import akka.http.scaladsl.model.{ContentType, HttpCharsets, MediaType, MessageEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import org.apache.openwhisk.connector.kafka.KafkaMetricRoute

import scala.concurrent.ExecutionContext

trait PrometheusExporter {
  def getReport(): MessageEntity
}

object PrometheusExporter {
  val textV4: ContentType = ContentType.apply(
    MediaType.textWithFixedCharset("plain", HttpCharsets.`UTF-8`).withParams(Map("version" -> "0.0.4")))
}

class PrometheusEventsApi(consumer: EventConsumer, prometheus: PrometheusExporter)(implicit ec: ExecutionContext) {
  val routes: Route = {
    get {
      path("ping") {
        if (consumer.isRunning) {
          complete("pong")
        } else {
          complete(ServiceUnavailable -> "Consumer not running")
        }
      } ~ path("metrics") {
        encodeResponse {
          complete(prometheus.getReport())
        }
      } ~ KafkaMetricRoute(consumer)
    }
  }
} 
Example 54
Source File: Entities.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller

import scala.concurrent.Future
import scala.language.postfixOps
import scala.util.Try
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.StatusCodes.PayloadTooLarge
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server.Directive0
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.server.RequestContext
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.RouteResult
import spray.json.JsonPrinter
import org.apache.openwhisk.common.TransactionId
import org.apache.openwhisk.core.entitlement.Privilege._
import org.apache.openwhisk.core.entitlement.Privilege
import org.apache.openwhisk.core.entitlement.Privilege.READ
import org.apache.openwhisk.core.entitlement.Resource
import org.apache.openwhisk.core.entity._
import org.apache.openwhisk.core.entity.ActivationEntityLimit
import org.apache.openwhisk.core.entity.size._
import org.apache.openwhisk.http.ErrorResponse.terminate
import org.apache.openwhisk.http.Messages

protected[controller] trait ValidateRequestSize extends Directives {

  protected def validateSize(check: => Option[SizeError])(implicit tid: TransactionId, jsonPrinter: JsonPrinter) =
    new Directive0 {
      override def tapply(f: Unit => Route) = {
        check map {
          case e: SizeError => terminate(PayloadTooLarge, Messages.entityTooBig(e))
        } getOrElse f(None)
      }
    }

  
  protected final def isEntity(n: String) = Try { EntityName(n) } isSuccess
} 
Example 55
Source File: CorsSupport.scala    From BusFloatingData   with Apache License 2.0 5 votes vote down vote up
package de.nierbeck.floating.data.server

import akka.http.scaladsl.model.HttpMethods._
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ Directive0, Route }

trait CorsSupport {

  lazy val allowedOriginHeader = `Access-Control-Allow-Origin`.*

  private def addAccessControlHeaders: Directive0 = {
    mapResponseHeaders { headers =>
      allowedOriginHeader +:
        `Access-Control-Allow-Credentials`(true) +:
        `Access-Control-Allow-Headers`("Content-Type", "X-Requested-With", "Authorization", "Token") +:
        headers
    }
  }

  private def preflightRequestHandler: Route = options {
    complete(HttpResponse(200).withHeaders(
      `Access-Control-Allow-Methods`(OPTIONS, POST, PUT, GET, DELETE)
    ))
  }

  def corsHandler(r: Route) = addAccessControlHeaders {
    preflightRequestHandler ~ r
  }

} 
Example 56
Source File: Routing.scala    From akka-visualmailbox   with Apache License 2.0 5 votes vote down vote up
package de.aktey.akka.visualmailbox.web

import akka.actor.ActorRef
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.scaladsl.Source
import de.heikoseeberger.akkasse.ServerSentEvent

import scala.concurrent.duration._


object Routing {
  def api(metricFlow: Source[String, ActorRef]): Route = pathPrefix("api") {
    import de.heikoseeberger.akkasse.EventStreamMarshalling._

    path("events") {
      complete {
        metricFlow
          .map(s => ServerSentEvent(s, "vmm"))
          .keepAlive(20.seconds, () => ServerSentEvent.heartbeat)
      }
    }
  }

  val static: Route = pathEndOrSingleSlash {
    getFromResource("web/index.html")
  } ~ getFromResourceDirectory("web")

  def root(metricFlow: Source[String, ActorRef]): Route = api(metricFlow) ~ static
} 
Example 57
Source File: Routes.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch14

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.MethodDirectives.{delete, get, post}
import akka.http.scaladsl.server.directives.PathDirectives.path
import akka.http.scaladsl.server.directives.RouteDirectives.complete
import akka.pattern.ask
import akka.util.Timeout
import ch14.Commands._
import ch14.Events.{
  ArticleCreated,
  ArticleDeleted,
  ArticlesPurchased,
  ArticlesRestocked
}

import scala.concurrent.{ExecutionContext, Future}

trait Routes extends JsonSupport {
  implicit def system: ActorSystem
  def inventory: ActorRef
  def config: Config

  implicit lazy val timeout: Timeout = config.timeout
  implicit lazy val ec: ExecutionContext = system.dispatcher

  lazy val articlesRoutes: Route =
    pathPrefix("articles") {
      concat(
        path(Segment) { name =>
          concat(
            post {
              val changedInventory: Future[Option[ArticleCreated]] =
                (inventory ? CreateArticle(name, 0))
                  .mapTo[Option[ArticleCreated]]
              onSuccess(changedInventory) {
                case None        => complete(StatusCodes.Conflict)
                case Some(event) => complete(StatusCodes.Created, event)
              }
            },
            delete {
              val changedInventory: Future[Option[ArticleDeleted]] =
                (inventory ? DeleteArticle(name)).mapTo[Option[ArticleDeleted]]
              rejectEmptyResponse {
                complete(changedInventory)
              }
            },
            get {
              complete((inventory ? GetArticle(name)).mapTo[Inventory])
            }
          )
        }
      )
    }

  lazy val inventoryRoutes: Route =
    path("inventory") {
      get {
        complete((inventory ? GetInventory).mapTo[Inventory])
      }
    } ~
      path("purchase") {
        post {
          entity(as[PurchaseArticles]) { order =>
            val response: Future[Option[ArticlesPurchased]] =
              (inventory ? order).mapTo[Option[ArticlesPurchased]]
            onSuccess(response) {
              case None        => complete(StatusCodes.Conflict)
              case Some(event) => complete(event)
            }
          }
        }
      } ~
      path("restock") {
        post {
          entity(as[RestockArticles]) { stock =>
            val response: Future[Option[ArticlesRestocked]] =
              (inventory ? stock).mapTo[Option[ArticlesRestocked]]
            complete(response)
          }
        }
      }


  lazy val routes: Route = articlesRoutes ~ inventoryRoutes

} 
Example 58
Source File: RoutesSpec.scala    From Learn-Scala-Programming   with MIT License 5 votes vote down vote up
package ch14

import akka.actor.ActorRef
import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch14.Commands.{PurchaseArticles, RestockArticles}
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.{Matchers, WordSpec}

import scala.concurrent.duration._

class RoutesSpec
    extends WordSpec
    with Matchers
    with ScalaFutures
    with ScalatestRouteTest
    with Routes {

  override lazy val config: Config = Config.load()

  DB.initialize(config.database)

  override lazy val inventory: ActorRef =
    system.actorOf(InventoryActor.props, "inventory")

  "Routes" should {
    "return no articles in the beginning" in {
      val request = HttpRequest(uri = "/inventory")
      implicit val timeout: Duration = 3.seconds
      request ~> routes ~> check {
        status shouldBe StatusCodes.OK
        contentType shouldBe ContentTypes.`application/json`
        entityAs[String] shouldBe """{"state":{}}"""
      }
    }
    "be able to add article (POST /articles/eggs)" in {
      val request = Post("/articles/eggs")
      request ~> routes ~> check {
        status shouldBe StatusCodes.Created
        contentType shouldBe ContentTypes.`application/json`
        entityAs[String] shouldBe """{"name":"eggs","count":0}"""
      }
    }
    "not be able to delete article (delete /articles/no)" in {
      val request = Delete("/articles/no-such-article")
      request ~> Route.seal(routes) ~> check {
        status shouldBe StatusCodes.NotFound
      }
    }
    "not be able to add article twice (POST /articles/eggs)" in {
      val request = Post("/articles/eggs")
      request ~> routes ~> check {
        status shouldBe StatusCodes.Conflict
      }
    }
    "be able to restock articles (POST /restock)" in {
      val restock = RestockArticles(Map("eggs" -> 10, "chocolate" -> 20))
      val entity  = Marshal(restock).to[MessageEntity].futureValue // futureValue is from ScalaFutures
      val request = Post("/restock").withEntity(entity)
      request ~> routes ~> check {
        status shouldBe StatusCodes.OK
        contentType shouldBe ContentTypes.`application/json`
        entityAs[String] shouldBe """{"stock":{"eggs":10,"chocolate":20}}"""
      }
    }
    "be able to purchase articles (POST /purchase)" in {
      val restock = PurchaseArticles(Map("eggs" -> 5, "chocolate" -> 10))
      val entity  = Marshal(restock).to[MessageEntity].futureValue // futureValue is from ScalaFutures
      val request = Post("/purchase").withEntity(entity)
      request ~> routes ~> check {
        status shouldBe StatusCodes.OK
        contentType shouldBe ContentTypes.`application/json`
        entityAs[String] shouldBe """{"order":{"eggs":5,"chocolate":10}}"""
      }
    }
    "not be able to purchase articles (POST /purchase)" in {
      val restock = PurchaseArticles(Map("eggs" -> 50, "chocolate" -> 10))
      val entity  = Marshal(restock).to[MessageEntity].futureValue // futureValue is from ScalaFutures
      val request = Post("/purchase").withEntity(entity)
      request ~> routes ~> check {
        status shouldBe StatusCodes.Conflict
      }
    }
  }
} 
Example 59
Source File: package.scala    From drunk   with Apache License 2.0 5 votes vote down vote up
package com.github.jarlakxen

import java.net.InetSocketAddress
import java.nio.channels.ServerSocketChannel

import scala.concurrent._
import scala.concurrent.duration._

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import akka.testkit._

import org.scalatest.BeforeAndAfterAll

package object drunk {

  trait TestHttpServer extends BeforeAndAfterAll {
    this: Spec =>

    implicit val system: ActorSystem = ActorSystem("drunk-test")
    implicit def executor = system.dispatcher
    implicit val materializer = ActorMaterializer()

    private def temporaryServerAddress(interface: String = "127.0.0.1"): InetSocketAddress = {
      val serverSocket = ServerSocketChannel.open()
      try {
        serverSocket.socket.bind(new InetSocketAddress(interface, 0))
        val port = serverSocket.socket.getLocalPort
        new InetSocketAddress(interface, port)
      } finally serverSocket.close()
    }

    private def temporaryServerHostnameAndPort(interface: String = "127.0.0.1"): (String, Int) = {
      val socketAddress = temporaryServerAddress(interface)
      (socketAddress.getHostName, socketAddress.getPort)
    }

    val (host, port) = temporaryServerHostnameAndPort()

    override protected def beforeAll(): Unit =
      Http().bindAndHandle(serverRoutes, host, port).futureValue

    override protected def afterAll(): Unit =
      TestKit.shutdownActorSystem(system)

    def serverRoutes: Route
  }

} 
Example 60
Source File: RestRoute.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.highlevelserver.route

import akka.actor.ActorRef
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.marshalling.ToResponseMarshaller
import akka.http.scaladsl.model.{ StatusCodes, Uri }
import akka.http.scaladsl.server.{ Directives, Route }
import akka.http.scaladsl.unmarshalling.FromRequestUnmarshaller
import akka.pattern.ask
import akka.util.Timeout
import com.github.dnvriend.component.highlevelserver.dto.PersonWithId
import com.github.dnvriend.component.highlevelserver.marshaller.Marshaller
import com.github.dnvriend.component.simpleserver.dto.http.Person

import scala.concurrent.Future

// see: akka.http.scaladsl.marshalling.ToResponseMarshallable
// see: akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers
object RestRoute extends Directives with SprayJsonSupport with Marshaller {
  def routes(personDb: ActorRef)(implicit timeout: Timeout, trmSingle: ToResponseMarshaller[PersonWithId], trmList: ToResponseMarshaller[List[PersonWithId]], fru: FromRequestUnmarshaller[Person]): Route = {
    pathEndOrSingleSlash {
      redirect(Uri("/api/person"), StatusCodes.PermanentRedirect)
    } ~
      pathPrefix("api" / "person") {
        get {
          path(IntNumber) { id =>
            println(s"PathEndsInNumber=$id")
            complete((personDb ? "findAll").mapTo[List[PersonWithId]])
          } ~
            pathEndOrSingleSlash {
              parameter("foo") { foo =>
                println(s"foo=$foo")
                complete((personDb ? "findAll").mapTo[List[PersonWithId]])
              } ~
                parameter('bar) { bar =>
                  println(s"bar=$bar")
                  complete((personDb ? "findAll").mapTo[List[PersonWithId]])
                } ~
                complete((personDb ? "findAll").mapTo[List[PersonWithId]])
            }
        } ~
          (post & pathEndOrSingleSlash & entity(as[Person])) { person =>
            complete((personDb ? person).mapTo[PersonWithId])
          }
      } ~
      path("failure") {
        pathEnd {
          complete(Future.failed[String](new RuntimeException("Simulated Failure")))
        }
      } ~
      path("success") {
        pathEnd {
          complete(Future.successful("Success!!"))
        }
      }
  }
} 
Example 61
Source File: CsvStreamingRoute.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver.route

import akka.http.scaladsl.common.{ CsvEntityStreamingSupport, EntityStreamingSupport }
import akka.http.scaladsl.marshalling.{ Marshaller, Marshalling }
import akka.http.scaladsl.model.ContentTypes
import akka.http.scaladsl.server.{ Directives, Route }
import akka.util.ByteString
import com.github.dnvriend.component.repository.PersonRepository
import com.github.dnvriend.component.simpleserver.dto.http.Person
import de.heikoseeberger.akkahttpplayjson.PlayJsonSupport

object CsvStreamingRoute extends Directives with PlayJsonSupport {
  implicit val personAsCsv = Marshaller.strict[Person, ByteString] { person =>
    Marshalling.WithFixedContentType(ContentTypes.`text/csv(UTF-8)`, () => {
      ByteString(List(person.name.replace(",", "."), person.age, person.married).mkString(","))
    })
  }

  implicit val csvStreamingSupport: CsvEntityStreamingSupport = EntityStreamingSupport.csv()

  def route(dao: PersonRepository): Route =
    path("stream" / IntNumber) { numberOfPeople =>
      pathEnd {
        get {
          complete(dao.people(numberOfPeople))
        }
      }
    }
} 
Example 62
Source File: SimpleDisjunctionRoute.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver.route

import akka.http.scaladsl.server.{ Directives, Route }
import com.github.dnvriend.component.simpleserver.dto.http.OrderDto
import com.github.dnvriend.component.simpleserver.marshaller.DisjunctionMarshaller.{ ErrorMessage, FatalError, NonFatalError }
import com.github.dnvriend.component.simpleserver.marshaller.{ DisjunctionMarshaller, Marshallers, ValidationMarshaller }

object SimpleDisjunctionRoute extends Directives with DisjunctionMarshaller with ValidationMarshaller with Marshallers {
  import scalaz._
  import Scalaz._
  final case class MyFatalError(description: String) extends FatalError
  final case class MyNonFatalError(description: String) extends NonFatalError

  def route: Route =
    pathPrefix("disjunction" / "simple") {
      (get & path("failure")) {
        complete("failure-left".left[String])
      } ~
        (get & path("success")) {
          complete("success-right".right[String])
        }
    } ~
      pathPrefix("disjunction" / "nel") {
        (get & path("string" / "failure")) {
          complete(("failure1".failureNel[String] *> "failure2".failureNel[String]).disjunction)
        } ~
          (get & path("nonfatal" / "failure")) {
            complete((MyNonFatalError("my-non-fatal-error-1").failureNel[OrderDto] *> MyNonFatalError("my-non-fatal-error-2").failureNel[OrderDto]).disjunction)
          } ~
          (get & path("fatal" / "failure")) {
            complete((MyFatalError("my-fatal-error-1").failureNel[OrderDto] *> MyFatalError("my-fatal-error-2").failureNel[OrderDto]).disjunction)
          } ~
          (get & path("combined" / "failure")) {
            complete((Validation.failureNel[ErrorMessage, OrderDto](MyFatalError("my-fatal-error-1")) *> Validation.failureNel[ErrorMessage, OrderDto](MyNonFatalError("my-non-fatal-error-1"))).disjunction)
          } ~
          (get & path("nonfatal" / "success")) {
            complete(OrderDto(1, "test-OrderDto").successNel[ErrorMessage].disjunction)
          }
      } ~
      pathPrefix("validation") {
        (get & path("failure")) {
          complete("failure".failureNel[String])
        } ~
          (get & path("success")) {
            complete("success".successNel[String])
          }
      }
} 
Example 63
Source File: SimpleServerRestRoutes.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver.route

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.{ Directives, Route }
import akka.pattern.CircuitBreaker
import akka.stream.Materializer
import com.github.dnvriend.component.repository.PersonRepository
import com.github.dnvriend.component.simpleserver.dto.http.{ Person, Ping }
import com.github.dnvriend.component.simpleserver.marshaller.Marshallers
import com.github.dnvriend.util.TimeUtil

import scala.concurrent.ExecutionContext

object SimpleServerRestRoutes extends Directives with Marshallers {
  def routes(dao: PersonRepository, cb: CircuitBreaker)(implicit mat: Materializer, ec: ExecutionContext): Route =
    logRequestResult("akka-http-test") {
      pathPrefix("person") {
        path("sync") {
          get {
            complete(dao.personSync)
          }
        } ~
          path("async") {
            get {
              complete(cb.withCircuitBreaker(dao.personAsync))
            }
          } ~
          path("failed") {
            get {
              complete(cb.withCircuitBreaker(dao.personAsyncFailed))
            }
          } ~
          pathEnd {
            get {
              complete(cb.withSyncCircuitBreaker(dao.personSync))
            }
          } ~
          (post & entity(as[Person])) { person =>
            complete(StatusCodes.Created)
          }
      } ~ pathPrefix("persons") {
        pathPrefix("strict" / IntNumber) { numberOfPersons =>
          pathEnd {
            get {
              complete(cb.withSyncCircuitBreaker(dao.listOfPersons(numberOfPersons)))
            }
          }
        } ~ JsonStreamingRoute.route(dao) ~ CsvStreamingRoute.route(dao)
      } ~ (get & pathPrefix("ping")) {
        complete(Ping(TimeUtil.timestamp))
      } ~ SimpleDisjunctionRoute.route ~ TryRoute.route
    }
} 
Example 64
Source File: JsonStreamingRoute.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver.route

import akka.event.LoggingAdapter
import akka.http.scaladsl.common.{ EntityStreamingSupport, JsonEntityStreamingSupport }
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.{ Directives, Route }
import akka.stream.Materializer
import akka.stream.scaladsl.Flow
import akka.util.ByteString
import com.github.dnvriend.component.repository.PersonRepository
import com.github.dnvriend.component.simpleserver.dto.http.Person
import com.github.dnvriend.component.simpleserver.marshaller.Marshallers

import scala.concurrent.ExecutionContext

object JsonStreamingRoute extends Directives with SprayJsonSupport with Marshallers {
  val start = ByteString.empty
  val sep = ByteString("\n")
  val end = ByteString.empty

  implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json()
    .withFramingRenderer(Flow[ByteString].intersperse(start, sep, end))
    .withParallelMarshalling(parallelism = 8, unordered = true)

  def route(dao: PersonRepository)(implicit mat: Materializer, ec: ExecutionContext): Route =
    path("stream" / IntNumber) { numberOfPersons =>
      (get & pathEnd) {
        complete(dao.people(numberOfPersons))
      }
    } ~
      (post & path("stream") & entity(asSourceOf[Person])) { people =>
        val total = people.log("people").runFold(0) { case (c, _) => c + 1 }
        complete(total.map(n => s"Received $n number of person"))
      }
} 
Example 65
Source File: TryRoute.scala    From akka-http-test   with Apache License 2.0 5 votes vote down vote up
package com.github.dnvriend.component.simpleserver.route

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.{ Directives, Route }
import spray.json.DefaultJsonProtocol

import scala.util.Try

object TryRoute extends Directives with SprayJsonSupport with DefaultJsonProtocol {
  def route: Route = {
    pathPrefix("try") {
      (get & path("failure")) {
        complete(Try((1 / 0).toString))
      } ~
        (get & path("success")) {
          complete(Try(1.toString))
        }
    }
  }
} 
Example 66
Source File: Routes.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.akka_oled

import akka.actor.typed.scaladsl.AskPattern._
import akka.actor.typed.{ActorRef, ActorSystem}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.Directives.{as, complete, concat, entity, get, onSuccess, pathPrefix, post, _}
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import com.lightbend.akka_oled.DistributedDataTracker.{Get, UpdateStatus}
import com.lightbend.akka_oled.Main.NodeStatus

import scala.concurrent.duration._

class Routes(tracker: ActorRef[DistributedDataTracker.Command])(implicit system: ActorSystem[_]) extends SprayJsonSupport {
  implicit val timeout: Timeout = 8.seconds

  val route: Route =
    pathPrefix("status" / "[0-9a-zA-Z]+".r) {
      node =>
        concat(
          get {
            onSuccess(tracker.ask[String](Get(node, _))) {
              value => complete(value + "\n")
            }
          },
          post {
            entity(as[NodeStatus]) { status =>
              tracker ! UpdateStatus(node, status.status)
              complete("Ok\n")
            }
          }
        )
    }

} 
Example 67
Source File: Routes.scala    From Pi-Akka-Cluster   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.akka_oled

import akka.actor.typed.ActorSystem
import akka.cluster.sharding.typed.scaladsl.ClusterSharding
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.Directives.{as, complete, concat, entity, get, onSuccess, pathPrefix, post, _}
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import com.lightbend.akka_oled.ClientEntity.{Get, PostPoints}
import com.lightbend.akka_oled.Main.AddPoints

import scala.concurrent.duration._

object Routes {

  case class NodeStatus(status: String)

}

class Routes(sharding: ClusterSharding)(implicit system: ActorSystem[_]) extends SprayJsonSupport {
  implicit val timeout: Timeout = 8.seconds
  implicit val scheduler = system.scheduler

  lazy val route: Route =
    pathPrefix("user" / "[0-9a-zA-Z]+".r) { username =>
      concat(
        get {
          val entityRef = sharding.entityRefFor(ClientEntity.TypeKey, username)
          onSuccess(entityRef ? Get(username)) {
            value: Int => complete(value.toString + "\n")
          }
        },
        post {
          entity(as[AddPoints]) { transaction =>
            val entityRef = sharding.entityRefFor(ClientEntity.TypeKey, username)
            onSuccess(entityRef ? PostPoints(username, transaction.points)) {
              result => complete(result)
            }
          }
        }
      )
    }

} 
Example 68
Source File: ChunkedEntitiesDocs.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package endpoints4s.akkahttp.server

import akka.http.scaladsl.server.Route
import endpoints4s.algebra
import endpoints4s.algebra.JsonStreamingExample

trait ChunkedEntitiesDocs extends algebra.ChunkedEntitiesDocs with ChunkedEntities {

  //#implementation
  import java.nio.file.Paths
  import akka.stream.scaladsl.FileIO

  val logoRoute: Route =
    logo.implementedBy { _ =>
      FileIO.fromPath(Paths.get("/foo/bar/logo.png")).map(_.toArray)
    }
  //#implementation

}

import scala.concurrent.duration.DurationInt

//#json-streaming
import akka.stream.scaladsl.Source
import endpoints4s.akkahttp.server

object JsonStreamingExampleServer
    extends JsonStreamingExample
    with server.Endpoints
    with server.ChunkedJsonEntities
    with server.JsonEntitiesFromSchemas {

  val routes =
    ticks.implementedBy(_ => Source.tick(0.seconds, 1.second, ()))

}
//#json-streaming 
Example 69
Source File: Server.scala    From scalachain   with MIT License 5 votes vote down vote up
package com.elleflorio.scalachain

import akka.actor.{ActorRef, ActorSystem}
import akka.cluster.pubsub.DistributedPubSub
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import com.elleflorio.scalachain.actor.Node
import com.elleflorio.scalachain.api.NodeRoutes
import com.elleflorio.scalachain.cluster.ClusterManager
import com.typesafe.config.{Config, ConfigFactory}

import scala.concurrent.Await
import scala.concurrent.duration.Duration

object Server extends App with NodeRoutes {

  implicit val system: ActorSystem = ActorSystem("scalachain")
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  val config: Config = ConfigFactory.load()
  val address = config.getString("http.ip")
  val port = config.getInt("http.port")
  val nodeId = config.getString("scalachain.node.id")

  lazy val routes: Route = statusRoutes ~ transactionRoutes ~ mineRoutes

  val clusterManager: ActorRef = system.actorOf(ClusterManager.props(nodeId), "clusterManager")
  val mediator: ActorRef = DistributedPubSub(system).mediator
  val node: ActorRef = system.actorOf(Node.props(nodeId, mediator), "node")

  Http().bindAndHandle(routes, address, port)
  println(s"Server online at http://$address:$port/")

  Await.result(system.whenTerminated, Duration.Inf)

} 
Example 70
Source File: NodeRoutes.scala    From scalachain   with MIT License 5 votes vote down vote up
package com.elleflorio.scalachain.api

import com.elleflorio.scalachain.actor.Node._
import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import com.elleflorio.scalachain.blockchain.{Chain, Transaction}
import com.elleflorio.scalachain.cluster.ClusterManager.GetMembers
import com.elleflorio.scalachain.utils.JsonSupport._

import scala.concurrent.Future
import scala.concurrent.duration._

trait NodeRoutes extends SprayJsonSupport {

  implicit def system: ActorSystem

  def node: ActorRef
  def clusterManager: ActorRef

  implicit lazy val timeout = Timeout(5.seconds)

  lazy val statusRoutes: Route = pathPrefix("status") {
    concat(
      pathEnd {
        concat(
          get {
            val statusFuture: Future[Chain] = (node ? GetStatus).mapTo[Chain]
            onSuccess(statusFuture) { status =>
              complete(StatusCodes.OK, status)
            }
          }
        )
      },
      pathPrefix("members") {
        concat(
          pathEnd {
            concat(
              get {
                val membersFuture: Future[List[String]] = (clusterManager ? GetMembers).mapTo[List[String]]
                onSuccess(membersFuture) { members =>
                  complete(StatusCodes.OK, members)
                }
              }
            )
          }
        )
      }
    )
  }

  lazy val transactionRoutes: Route = pathPrefix("transactions") {
    concat(
      pathEnd {
        concat(
          get {
            val transactionsRetrieved: Future[List[Transaction]] =
              (node ? GetTransactions).mapTo[List[Transaction]]
            onSuccess(transactionsRetrieved) { transactions =>
              complete(transactions.toList)
            }
          },
          post {
            entity(as[Transaction]) { transaction =>
              val transactionCreated: Future[Int] =
                (node ? AddTransaction(transaction)).mapTo[Int]
              onSuccess(transactionCreated) { done =>
                complete((StatusCodes.Created, done.toString))
              }
            }
          }
        )
      }
    )
  }

  lazy val mineRoutes: Route = pathPrefix("mine") {
    concat(
      pathEnd {
        concat(
          get {
            node ! Mine
            complete(StatusCodes.OK)
          }
        )
      }
    )
  }

} 
Example 71
Source File: package.scala    From healthchecks   with MIT License 5 votes vote down vote up
package com.github.everpeace.healthchecks

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer

import scala.concurrent.{ExecutionContext, Future}

package object k8s {

  private def configPathRoot = "k8s_probe"

  private def config(system: ActorSystem, subPath: String = "") = {
    val path =
      if (subPath.nonEmpty) configPathRoot + "." + subPath else configPathRoot
    system.settings.config.getConfig(path)
  }

  def livenessProbe(
      checks: HealthCheck*
    )(implicit
      system: ActorSystem,
      ec: ExecutionContext
    ) = {
    LivenessProbe(checks.toList, config(system, "path").getString("liveness"), ec)
  }

  def readinessProbe(
      checks: HealthCheck*
    )(implicit
      system: ActorSystem,
      ec: ExecutionContext
    ) = {
    ReadinessProbe(checks.toList, config(system, "path").getString("readiness"), ec)
  }

  def bindAndHandleProbes(
      probe: K8sProbe,
      probes: K8sProbe*
    )(implicit
      system: ActorSystem,
      am: ActorMaterializer
    ): Future[Http.ServerBinding] = {
    val host = config(system).getString("host")
    val port = config(system).getInt("port")
    val routes = (probe +: probes).toList
      .map(_.toRoute)
      .reduce((r1: Route, r2: Route) => r1 ~ r2)
    Http(system).bindAndHandle(routes, host, port)
  }
} 
Example 72
Source File: HealthCheckRoutes.scala    From healthchecks   with MIT License 5 votes vote down vote up

package com.github.everpeace.healthchecks.route

import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.directives.PathDirectives
import akka.http.scaladsl.server.{PathMatchers, Route}
import cats.data.Validated.{Invalid, Valid}
import com.github.everpeace.healthchecks.{HealthCheck, HealthCheckResult}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
import io.circe.JsonObject
import io.circe.generic.JsonCodec
import io.circe.generic.auto._

import scala.collection.convert.DecorateAsScala
import scala.concurrent.{ExecutionContext, Future}

object HealthCheckRoutes extends DecorateAsScala {

  @JsonCodec case class HealthCheckResultJson(
      name: String,
      severity: String,
      status: String,
      messages: List[String])

  @JsonCodec case class ResponseJson(status: String, check_results: List[HealthCheckResultJson])

  private def status(s: Boolean) = if (s) "healthy" else "unhealthy"

  private def statusCode(s: Boolean) = if (s) OK else ServiceUnavailable

  private def toResultJson(check: HealthCheck, result: HealthCheckResult) =
    HealthCheckResultJson(
      check.name,
      check.severity.toString,
      status(result.isValid),
      result match {
        case Valid(_)        => List()
        case Invalid(errors) => errors.toList
      }
    )

  def health(
      checks: HealthCheck*
    )(implicit
      ec: ExecutionContext
    ): Route = health("health", checks.toList)

  def health(
      path: String,
      checks: List[HealthCheck]
    )(implicit
      ec: ExecutionContext
    ): Route = {
    require(checks.nonEmpty, "checks must not empty.")
    require(
      checks.map(_.name).toSet.size == checks.length,
      s"HealthCheck name should be unique (given HealthCheck names = [${checks.map(_.name).mkString(",")}])."
    )
    val rootSlashRemoved =
      if (path.startsWith("/")) path.substring(1) else path
    PathDirectives.path(PathMatchers.separateOnSlashes(rootSlashRemoved)) {
      parameter("full" ? false) { full =>
        get {
          def isHealthy(checkAndResults: List[(HealthCheck, HealthCheckResult)]) =
            checkAndResults.forall(cr => cr._2.isValid || (!cr._1.severity.isFatal))
          val checkAndResultsFuture = Future.traverse(checks) { c =>
            c.run().map(c -> _)
          }
          if (full) {
            complete {
              checkAndResultsFuture.map { checkAndResults =>
                val healthy = isHealthy(checkAndResults)
                statusCode(healthy) -> ResponseJson(
                  status(healthy),
                  checkAndResults.map {
                    case (check, result) => toResultJson(check, result)
                  }
                )
              }
            }
          } else {
            complete {
              checkAndResultsFuture.map { checkAndResults =>
                statusCode(isHealthy(checkAndResults)) -> JsonObject.empty
              }
            }
          }
        }
      }
    }
  }
} 
Example 73
Source File: TopicApi.scala    From sns   with Apache License 2.0 5 votes vote down vote up
package me.snov.sns.api

import akka.actor.ActorRef
import akka.actor.Status.Success
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import me.snov.sns.actor.SubscribeActor.{CmdListTopics, CmdDeleteTopic, CmdCreateTopic}
import me.snov.sns.model.Topic
import me.snov.sns.response.TopicResponse

import scala.concurrent.ExecutionContext

object TopicApi {
  private val namePattern = """([\w+_-]{1,256})""".r
  private val arnPattern = """([\w+_:-]{1,512})""".r

  def route(actor: ActorRef)(implicit timeout: Timeout, ec: ExecutionContext): Route = {
    pathSingleSlash {
      formField('Action ! "CreateTopic") {
        formField('Name) {
          case namePattern(name) => complete {
            (actor ? CmdCreateTopic(name)).mapTo[Topic].map {
              TopicResponse.create
            }
          }
          case _ => complete(HttpResponse(400, entity = "InvalidParameter: invalid topic name"))
        } ~
        complete(HttpResponse(400, entity = "Topic name is missing"))
      } ~
      formField('Action ! "DeleteTopic") {
        formField('TopicArn) {
          case arnPattern(arn) => complete {
            (actor ? CmdDeleteTopic(arn)).map {
              case Success => TopicResponse.delete
              case _ => HttpResponse(404, entity = "NotFound")
            }
          }
          case _ => complete(HttpResponse(400, entity = "Invalid topic ARN"))
        } ~
        complete(HttpResponse(404, entity = "NotFound"))
      } ~ 
      formField('Action ! "ListTopics") {
        complete {
          (actor ? CmdListTopics).mapTo[Iterable[Topic]].map {
            TopicResponse.list
          }
        }
      }
    }
  }
} 
Example 74
Source File: PublishApi.scala    From sns   with Apache License 2.0 5 votes vote down vote up
package me.snov.sns.api

import akka.actor.ActorRef
import akka.event.Logging

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import me.snov.sns.actor.PublishActor.CmdPublish
import me.snov.sns.model.{Message, MessageAttribute, TopicNotFoundException}
import me.snov.sns.response.PublishResponse
import spray.json.DefaultJsonProtocol._
import spray.json._

import scala.concurrent.{ExecutionContext, Future}

case class InvalidTopicArnException(msg: String) extends Exception(msg)

object PublishApi {
  private val arnPattern = """([\w+_:-]{1,512})""".r

  def route(actorRef: ActorRef)(implicit timeout: Timeout, ec: ExecutionContext): Route = {
    pathSingleSlash {
      formField('Action ! "Publish") {
        formFieldSeq { fields =>
          val messageAttributes: Map[String, MessageAttribute] = MessageAttribute.parse(fields)
          formFields('TopicArn.?, 'TargetArn.?, 'MessageStructure.?, 'Message) { (topicArnMaybe, targetArnMaybe, messageStructure, message) =>
            try {
              topicArn(topicArnMaybe, targetArnMaybe) match {
                case arnPattern(topic) => complete {
                  val bodies = messageStructure match {
                    case Some("json") => message.parseJson.asJsObject.convertTo[Map[String, String]]
                    case Some(_) => throw new RuntimeException("Invalid MessageStructure value");
                    case None => Map("default" -> message)
                  }
                  (actorRef ? CmdPublish(topic, bodies, messageAttributes)).collect {
                    case m: Message => PublishResponse.publish(m)
                  }.recover {
                    case t: TopicNotFoundException => PublishResponse.topicNotFound(t.getMessage)
                    case t: Throwable => HttpResponse(500, entity = t.getMessage)
                  }
                }
                case _ => complete(HttpResponse(400, entity = "Invalid topic ARN"))
              }
            } catch {
              case e: InvalidTopicArnException => complete(HttpResponse(400, entity = e.getMessage))
              case e: RuntimeException => complete(HttpResponse(400, entity = e.getMessage))
            }
          }
        } ~
          complete(HttpResponse(400, entity = "TopicArn is required"))
      }
    }
  }

  private def topicArn(topicArnMaybe: Option[String], targetArnMaybe: Option[String]): String = {
    topicArnMaybe.getOrElse(targetArnMaybe.getOrElse(throw InvalidTopicArnException("Neither TopicArn nor TargetArn provided")))
  }
} 
Example 75
Source File: SubscribeApi.scala    From sns   with Apache License 2.0 5 votes vote down vote up
package me.snov.sns.api

import akka.actor.ActorRef
import akka.actor.Status.{Success, Failure}
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import me.snov.sns.actor.SubscribeActor.{CmdListSubscriptions, CmdListSubscriptionsByTopic, CmdSubscribe, CmdUnsubscribe,CmdSetSubscriptionAttributes,CmdGetSubscriptionAttributes}
import me.snov.sns.model.Subscription
import me.snov.sns.response.SubscribeResponse

import scala.concurrent.ExecutionContext

object SubscribeApi {
  private val arnPattern = """([\w+_:-]{1,512})""".r

  def route(actorRef: ActorRef)(implicit timeout: Timeout, ec: ExecutionContext): Route = {
    pathSingleSlash {
      formField('Action ! "Subscribe") {
        formFields('Endpoint, 'Protocol, 'TopicArn) { (endpoint, protocol, topicArn) =>
          complete {
            (actorRef ? CmdSubscribe(topicArn, protocol, endpoint)).mapTo[Subscription] map {
              SubscribeResponse.subscribe
            }
          }
        } ~
          complete(HttpResponse(400, entity = "Endpoint, Protocol, TopicArn are required"))
      } ~
        formField('Action ! "ListSubscriptionsByTopic") {
          formField('TopicArn) {
            case arnPattern(topicArn) => complete {
              (actorRef ? CmdListSubscriptionsByTopic(topicArn)).mapTo[Iterable[Subscription]] map {
                SubscribeResponse.listByTopic
              }
            }
            case _ => complete(HttpResponse(400, entity = "Invalid topic ARN"))
          } ~
            complete(HttpResponse(400, entity = "TopicArn is missing"))
        } ~
        formField('Action ! "ListSubscriptions") {
          complete {
            (actorRef ? CmdListSubscriptions()).mapTo[Iterable[Subscription]] map {
              SubscribeResponse.list
            }
          }
        } ~
        formField('Action ! "Unsubscribe") {
          formField('SubscriptionArn) { (arn) =>
            complete {
              (actorRef ? CmdUnsubscribe(arn)).map {
                case Success => SubscribeResponse.unsubscribe
                case _ => HttpResponse(404, entity = "NotFound")
              }
            }
          } ~
          complete(HttpResponse(400, entity = "SubscriptionArn is missing"))
        } ~
        formField('Action ! "SetSubscriptionAttributes") {
          formField('SubscriptionArn, 'AttributeName, 'AttributeValue) { (arn, name, value) =>
            complete {
              (actorRef ? CmdSetSubscriptionAttributes(arn, name, value)).map {
                case Success => SubscribeResponse.setSubscriptionAttributes
                case Failure(ex) => HttpResponse(404, entity = "NotFound")
              }
            }
          } ~
          complete(HttpResponse(400, entity = "SubscriptionArn is missing"))
        } ~
        formField('Action ! "GetSubscriptionAttributes") {
          formField('SubscriptionArn) { (arn) =>
            complete {
              (actorRef ? CmdGetSubscriptionAttributes(arn)).mapTo[Option[Map[String,String]]] map { attributes =>
                attributes
                  .map(SubscribeResponse.getSubscriptionAttributes)
                  .getOrElse {
                    HttpResponse(404, entity = "Not Found")
                  }
              }
            }
          } ~
          complete(HttpResponse(400, entity = "SubscriptionArn is missing"))
        }
    }
  }
} 
Example 76
Source File: DonutRoute.scala    From scala-for-beginners   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.donutstore.routes

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.allaboutscala.donutstore.common.Donut
import com.allaboutscala.donutstore.config.DonutStoreConfig
import com.allaboutscala.donutstore.data.DataApi
import com.allaboutscala.donutstore.marshalling.JsonSupport

import scala.util.{Failure, Success}



class DonutRoute extends HttpRoute with JsonSupport {
  override def routes()(implicit config: DonutStoreConfig, dataApi: DataApi): Route = {
    path("add-donut") {
      post {
        entity(as[Donut]) { donut =>
          onComplete(dataApi.createDonut(donut)) {
            case Success(createMessage) => complete(StatusCodes.Created, createMessage)
            case Failure(ex) => complete(s"Failed to create donut, exception = ${ex.getMessage}")
          }
        }
      } ~
      get {
        complete(StatusCodes.MethodNotAllowed)
      }
    } ~
      path("donuts") {
      get {
        onComplete(dataApi.fetchDonuts()) {
          case Success(donuts) => complete(StatusCodes.OK, donuts)
          case Failure(ex) => complete(s"Failed to fetch donuts, exception = ${ex.getMessage}")
        }
      }
    } ~
    path("donuts" / Segment) { donutName =>
      delete {
        onComplete(dataApi.deleteDonut(donutName)) {
          case Success(deleteMessage) => complete(StatusCodes.OK, deleteMessage)
          case Failure(ex) => complete(s"Failed to delete donut, exception = ${ex.getMessage}")
        }
      }
    } ~
    path("donuts" / Segment) { donutName =>
      post {
        parameter("ingredients") { ingredients =>
          val donutIngredients = ingredients.split(",").toList
          val donut = Donut(donutName, donutIngredients)
          onComplete(dataApi.updateDonutIngredients(donut)) {
            case Success(updateMessage) => complete(StatusCodes.OK, updateMessage)
            case Failure(ex) => complete(s"Failed to update ingredients, exception = ${ex.getMessage}")
          }
        }
      }
    }
  }
} 
Example 77
Source File: ApiVersionRoute.scala    From scala-for-beginners   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.donutstore.routes


import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives.{complete, get, path, _}
import akka.http.scaladsl.server.Route
import com.allaboutscala.donutstore.config.DonutStoreConfig
import com.allaboutscala.donutstore.data.DataApi

import scala.util.Try



class ApiVersionRoute extends HttpRoute {
  import spray.json._

  override def routes()(implicit config: DonutStoreConfig, dataApi: DataApi): Route = {
    val apiVersion =
      s"""
         |{
         | "app": "${config.app}",
         | "version": "${config.httpServer.apiVersion}"
         |}""".stripMargin

    path("api-version") {
      get {
        parameter("prettyPrint" ? "true") { prettyPrint => // the prettyPrint parameter is optional and we also default to true
          val shouldPrettyPrint = Try(prettyPrint.toBoolean).getOrElse(true) // we'll default to pretty print
          val apiVersionOutput = if (shouldPrettyPrint) apiVersion.parseJson.prettyPrint else apiVersion.parseJson.toString
          complete(HttpEntity(ContentTypes.`application/json`, apiVersionOutput))
        }
      }
    }
  }
} 
Example 78
Source File: SupervisorService.scala    From incubator-retired-gearpump   with Apache License 2.0 5 votes vote down vote up
package org.apache.gearpump.services

import scala.concurrent.Future
import scala.util.{Failure, Success}

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.Materializer

import org.apache.gearpump.cluster.AppMasterToMaster.{GetWorkerData, WorkerData}
import org.apache.gearpump.cluster.ClientToMaster._
import org.apache.gearpump.cluster.worker.WorkerId
import org.apache.gearpump.services.SupervisorService.{Path, Status}
import org.apache.gearpump.util.ActorUtil._
// NOTE: This cannot be removed!!!
import org.apache.gearpump.services.util.UpickleUtil._


  private def authorize(internal: Route): Route = {
    if (supervisor == null) {
      failWith(new Exception("API not enabled, cannot find a valid supervisor! " +
        "Please make sure Gearpump is running on top of YARN or other resource managers"))
    } else {
      internal
    }
  }

  protected override def doRoute(implicit mat: Materializer) = pathPrefix("supervisor") {
    pathEnd {
      get {
        val path = if (supervisor == null) {
          null
        } else {
          supervisor.path.toString
        }
        complete(write(Path(path)))
      }
    } ~
    path("status") {
      post {
        if (supervisor == null) {
          complete(write(Status(enabled = false)))
        } else {
          complete(write(Status(enabled = true)))
        }
      }
    } ~
    path("addworker" / IntNumber) { workerCount =>
      post {
        authorize {
          onComplete(askActor[CommandResult](supervisor, AddWorker(workerCount))) {
            case Success(value) =>
              complete(write(value))
            case Failure(ex) =>
              failWith(ex)
          }
        }
      }
    } ~
    path("removeworker" / Segment) { workerIdString =>
      post {
        authorize {
          val workerId = WorkerId.parse(workerIdString)
          def future(): Future[CommandResult] = {
            askWorker[WorkerData](master, workerId, GetWorkerData(workerId)).flatMap{workerData =>
              val containerId = workerData.workerDescription.resourceManagerContainerId
              askActor[CommandResult](supervisor, RemoveWorker(containerId))
            }
          }

          onComplete[CommandResult](future()) {
            case Success(value) =>
              complete(write(value))
            case Failure(ex) =>
              failWith(ex)
          }
        }
      }
    }
  }
}

object SupervisorService {
  case class Status(enabled: Boolean)

  case class Path(path: String)
} 
Example 79
Source File: BasicService.scala    From incubator-retired-gearpump   with Apache License 2.0 5 votes vote down vote up
package org.apache.gearpump.services

import scala.concurrent.ExecutionContext

import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.CacheDirectives.{`max-age`, `no-cache`}
import akka.http.scaladsl.model.headers.`Cache-Control`
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.Materializer

import org.apache.gearpump.util.{Constants, LogUtil}
// NOTE: This cannot be removed!!!
import org.apache.gearpump.services.util.UpickleUtil._

trait RouteService {
  def route: Route
}


trait BasicService extends RouteService {

  implicit def system: ActorSystem

  implicit def timeout: akka.util.Timeout = Constants.FUTURE_TIMEOUT

  implicit def ec: ExecutionContext = system.dispatcher

  protected def doRoute(implicit mat: Materializer): Route

  protected def prefix = Slash ~ "api" / s"$REST_VERSION"

  protected val LOG = LogUtil.getLogger(getClass)

  protected def cache = false
  private val noCacheHeader = `Cache-Control`(`no-cache`, `max-age`(0L))

  def route: Route = encodeResponse {
    extractMaterializer { implicit mat =>
      rawPathPrefix(prefix) {
        if (cache) {
          doRoute(mat)
        } else {
          respondWithHeader(noCacheHeader) {
            doRoute(mat)
          }
        }
      }
    }
  }
} 
Example 80
Source File: RestServices.scala    From incubator-retired-gearpump   with Apache License 2.0 5 votes vote down vote up
package org.apache.gearpump.services

import scala.concurrent.Await
import scala.concurrent.duration._

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Route, _}
import akka.stream.ActorMaterializer
import akka.util.Timeout
import org.apache.commons.lang.exception.ExceptionUtils

import org.apache.gearpump.jarstore.JarStoreClient
import org.apache.gearpump.util.{Constants, LogUtil}
// NOTE: This cannot be removed!!!
import org.apache.gearpump.services.util.UpickleUtil._


class RestServices(master: ActorRef, mat: ActorMaterializer, system: ActorSystem)
  extends RouteService {

  private val LOG = LogUtil.getLogger(getClass)

  implicit val timeout = Constants.FUTURE_TIMEOUT

  private val config = system.settings.config

  private val jarStoreClient = new JarStoreClient(config, system)

  private val securityEnabled = config.getBoolean(
    Constants.GEARPUMP_UI_SECURITY_AUTHENTICATION_ENABLED)

  private val supervisorPath = system.settings.config.getString(
    Constants.GEARPUMP_SERVICE_SUPERVISOR_PATH)

  private val myExceptionHandler: ExceptionHandler = ExceptionHandler {
    case ex: Throwable => {
      extractUri { uri =>
        LOG.error(s"Request to $uri could not be handled normally", ex)
        complete(InternalServerError, ExceptionUtils.getStackTrace(ex))
      }
    }
  }

  // Makes sure staticRoute is the final one, as it will try to lookup resource in local path
  // if there is no match in previous routes
  private val static = new StaticService(system, supervisorPath).route

  def supervisor: ActorRef = {
    if (supervisorPath == null || supervisorPath.isEmpty()) {
      null
    } else {
      val actorRef = system.actorSelection(supervisorPath).resolveOne()
      Await.result(actorRef, new Timeout(Duration.create(5, "seconds")).duration)
    }
  }

  override def route: Route = {
    if (securityEnabled) {
      val security = new SecurityService(services, system)
      handleExceptions(myExceptionHandler) {
        security.route ~ static
      }
    } else {
      handleExceptions(myExceptionHandler) {
        services.route ~ static
      }
    }
  }

  private def services: RouteService = {

    val admin = new AdminService(system)
    val masterService = new MasterService(master, jarStoreClient, system)
    val worker = new WorkerService(master, system)
    val app = new AppMasterService(master, jarStoreClient, system)
    val sup = new SupervisorService(master, supervisor, system)

    new RouteService {
      override def route: Route = {
        admin.route ~ sup.route ~ masterService.route ~ worker.route ~ app.route
      }
    }
  }
} 
Example 81
Source File: Startup.scala    From 006877   with MIT License 5 votes vote down vote up
package com.goticks

import scala.concurrent.Future
import scala.util.{Failure, Success}

import akka.actor.ActorSystem
import akka.event.Logging

import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.server.Route

import akka.stream.ActorMaterializer

trait Startup extends RequestTimeout {
  def startup(api: Route)(implicit system: ActorSystem) = {
    val host = system.settings.config.getString("http.host") // 설정에서 호스트와 포트를 가져온다
    val port = system.settings.config.getInt("http.port")
    startHttpServer(api, host, port)
  }

  def startHttpServer(api: Route, host: String, port: Int)
      (implicit system: ActorSystem) = {
    implicit val ec = system.dispatcher  // bindAndHandle에는 암시적인 ExecutionContext가 필요하다
    implicit val materializer = ActorMaterializer()
    val bindingFuture: Future[ServerBinding] =
    Http().bindAndHandle(api, host, port) // HTTP 서버를 시작한다
   
    val log = Logging(system.eventStream, "go-ticks")
    bindingFuture.map { serverBinding =>
      log.info(s"RestApi bound to ${serverBinding.localAddress} ")
    }.onComplete { 
      case Success(v) =>
	  case Failure(ex) =>
        log.error(ex, "Failed to bind to {}:{}!", host, port)
        system.terminate()
    }
  }
} 
Example 82
Source File: GitHubHosted2048Bot.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.model.Uri.{Path, Query}
import akka.http.scaladsl.model.headers.{HttpOrigin, HttpOriginRange}

import ch.megard.akka.http.cors.scaladsl.model.{HttpHeaderRange, HttpOriginMatcher}

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import cats.instances.future._
import cats.syntax.functor._
import ch.megard.akka.http.cors.scaladsl.CorsDirectives.cors
import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings
import com.bot4s.telegram.api.declarative.{Callbacks, Commands}
import com.bot4s.telegram.api.{GameManager, Payload}
import com.bot4s.telegram.future.Polling
import com.bot4s.telegram.methods.SendGame

import scala.concurrent.Future


class GitHubHosted2048Bot(token: String, gameManagerHost: String)
  extends AkkaExampleBot(token)
    with Polling
    with Commands[Future]
    with Callbacks[Future]
    with GameManager {

  override val port: Int = 8080

  val Play2048 = "play_2048"
  val GitHubPages = Uri("https://mukel.github.io")

  onCommand(Play2048 or "2048" or "start") { implicit msg =>
    request(
      SendGame(msg.source, Play2048)
    ).void
  }

  onCallbackQuery { implicit cbq =>
    val acked = cbq.gameShortName.collect {
      case Play2048 =>
        val payload = Payload.forCallbackQuery(gameManagerHost)

        val url = GitHubPages
          .withPath(Path(s"/$Play2048/index.html"))
          .withQuery(Query("payload" -> payload.base64Encode))

        ackCallback(url = Some(url.toString()))
    }

    acked.getOrElse(ackCallback()).void
  }

  // Enable CORS for GitHub Pages.
  // Allows GitHub Pages to call cross-domain getScores and setScore.
  private val allowGitHub = CorsSettings.defaultSettings
    .withAllowedOrigins(HttpOriginMatcher(HttpOrigin(GitHubPages.toString())))

  override def routes: Route =
    super.routes ~
      cors(allowGitHub) {
        gameManagerRoute
      }
} 
Example 83
Source File: SelfHosted2048Bot.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.model.Uri.{Path, Query}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import cats.instances.future._
import cats.syntax.functor._
import com.bot4s.telegram.api.declarative.{Callbacks, Commands}
import com.bot4s.telegram.api.{AkkaDefaults, GameManager, Payload}
import com.bot4s.telegram.future.Polling
import com.bot4s.telegram.methods.SendGame

import scala.concurrent.Future


class SelfHosted2048Bot(token: String, gameManagerHost: String)
  extends ExampleBot(token)
    with Polling
    with AkkaDefaults
    with Callbacks[Future]
    with GameManager
    with Commands[Future] {

  override val port: Int = 8080

  val Play2048 = "play_2048"

  onCommand(Play2048 or "2048" or "start") { implicit msg =>
    request(
      SendGame(msg.source, Play2048)
    ).void
  }

  onCallbackQuery { implicit cbq =>
    val acked = cbq.gameShortName.collect {
      case Play2048 =>
        val payload = Payload.forCallbackQuery(gameManagerHost)

        val url = Uri(gameManagerHost)
          .withPath(Path(s"/$Play2048/index.html"))
          .withQuery(Query("payload" -> payload.base64Encode))

        ackCallback(url = Some(url.toString()))
    }

    acked.getOrElse(ackCallback()).void
  }

  override def routes: Route =
    super.routes ~
      gameManagerRoute ~ {
      pathPrefix(Play2048) {
        getFromResourceDirectory(Play2048)
      }
    }
} 
Example 84
Source File: WebRoutes.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.api

import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.bot4s.telegram.future.BotExecutionContext
import slogging.StrictLogging

import scala.concurrent.{Future, Promise}

trait WebRoutes extends BotBase[Future] with StrictLogging {
  _: BotExecutionContext with AkkaImplicits =>

  val port: Int
  val interfaceIp: String = "::0"

  def routes: Route = reject

  private var bindingFuture: Future[Http.ServerBinding] = _

  @volatile private var eol: Promise[Unit] = _

  abstract override def run(): Future[Unit] = synchronized {
    if (eol != null) {
      throw new RuntimeException("Bot is already running")
    }

    bindingFuture = Http().bindAndHandle(routes, interfaceIp, port)
    bindingFuture.foreach { _ =>
      logger.info(s"Listening on $interfaceIp:$port")
    }

    sys.addShutdownHook {
      shutdown()
    }

    eol = Promise[Unit]()
    val t = Future.sequence(Seq(eol.future, super.run()))
    t.map(_ => ())
  }

  abstract override def shutdown(): Unit = synchronized {
    if (eol == null) {
      throw new RuntimeException("Bot is not running")
    }
    super.shutdown()
    for {
       b <- bindingFuture
       _ <- b.unbind()
       t <- system.terminate()
    }  {
      eol.success(())
      eol = null
    }
  }
} 
Example 85
Source File: Webhook.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.api

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.bot4s.telegram.future.BotExecutionContext
import com.bot4s.telegram.methods.SetWebhook
import com.bot4s.telegram.models.{InputFile, Update}
import slogging.StrictLogging

import scala.concurrent.Future
import scala.util.control.NonFatal


  def certificate: Option[InputFile] = None

  def webhookReceiver: Route = {
    entity(as[Update]) { update =>
      try {
        receiveUpdate(update, None)
      } catch {
        case NonFatal(e) =>
          logger.error("Caught exception in update handler", e)
      }
      complete(StatusCodes.OK)
    }
  }

  abstract override def routes: Route = webhookRoute ~ super.routes

  abstract override def run(): Future[Unit] = {
    request(
      SetWebhook(
        url = webhookUrl,
        certificate = certificate,
        allowedUpdates = allowedUpdates)).flatMap {
      case true => super.run() // spawn WebRoutes
      case false =>
        logger.error("Failed to set webhook")
        throw new RuntimeException("Failed to set webhook")
    }
  }
} 
Example 86
Source File: GameManager.scala    From telegram   with Apache License 2.0 5 votes vote down vote up
package com.bot4s.telegram.api

import java.net.URLDecoder
import java.nio.charset.StandardCharsets
import java.util.Base64

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Directive1, Route}
import com.bot4s.telegram.marshalling
import com.bot4s.telegram.methods.{GetGameHighScores, SetGameScore}
import com.bot4s.telegram.models.{CallbackQuery, ChatId, User}
import com.bot4s.telegram.future.BotExecutionContext
import io.circe.generic.extras.semiauto._
import io.circe.generic.semiauto.deriveDecoder
import io.circe.{Decoder, Encoder}

import scala.concurrent.Future
import scala.util.{Failure, Success}


case class Payload(
                    user            : User,
                    chatId          : Option[ChatId] = None,
                    messageId       : Option[Int] = None,
                    inlineMessageId : Option[String] = None,
                    gameManagerHost : String,
                    gameShortName   : String) {

  def toGetGameHighScores = GetGameHighScores(user.id, chatId, messageId, inlineMessageId)

  def base64Encode: String = {
    val payloadJson = marshalling.toJson[Payload](this)
    val encodedPayload = Base64.getEncoder.encodeToString(
      payloadJson.getBytes(StandardCharsets.UTF_8))

    encodedPayload
  }
}

object Payload {

  def base64Decode(encodedPayload: String): Payload = {
    val base64payload = URLDecoder.decode(encodedPayload, "UTF-8")
    val jsonPayload = new String(Base64.getDecoder.decode(base64payload),
      StandardCharsets.UTF_8)
    val payload = marshalling.fromJson[Payload](jsonPayload)

    payload
  }

  def forCallbackQuery(gameManagerHost: String)(implicit cbq: CallbackQuery): Payload = {
    Payload(
      cbq.from,
      cbq.message.map(_.source),
      cbq.message.map(_.messageId),
      cbq.inlineMessageId,
      gameManagerHost,
      cbq.gameShortName.get) // throws if not a game callback
  }

  import marshalling._
  implicit val payloadEncoder: Encoder[Payload] = deriveEncoder[Payload]
  implicit val payloadDecoder: Decoder[Payload] = deriveDecoder[Payload]
} 
Example 87
Source File: WebSocketWorker.scala    From chordial   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package com.tristanpenman.chordial.demo

import akka.actor._
import akka.http.scaladsl.model.ws.{Message, TextMessage}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.scaladsl.{Flow, Source}
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._

import scala.concurrent.ExecutionContext

final class WebSocketWorker(governor: ActorRef, eventsSource: Source[TextMessage, _])(implicit val ec: ExecutionContext)
    extends WebService {

  def route =
    // scalafmt: { indentOperator = spray }
    cors() {
      routes(governor) ~
      pathPrefix("eventstream")(getFromResourceDirectory("webapp")) ~
      handleWebSocketMessages(Flow[Message].take(0).prepend(eventsSource))
    }
}

object WebSocketWorker {
  def apply(nodeRef: ActorRef, eventsSource: Source[TextMessage, _])(
      implicit ec: ExecutionContext): Route =
    new WebSocketWorker(nodeRef, eventsSource).route
} 
Example 88
Source File: PhoneBookWebService.scala    From udash-demos   with GNU General Public License v3.0 5 votes vote down vote up
package io.udash.demos.rest.api

import akka.http.scaladsl.marshalling._
import akka.http.scaladsl.model.{HttpEntity, MediaTypes, StatusCodes}
import com.avsystem.commons.serialization.GenCodec
import io.udash.demos.rest.model._
import io.udash.demos.rest.services.{ContactService, InMemoryContactService, InMemoryPhoneBookService, PhoneBookService}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{RequestContext, Route}
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import com.avsystem.commons.serialization.json.{JsonStringInput, JsonStringOutput}


trait PhoneBookWebServiceSpec {
  private val staticsDir = "frontend/target/UdashStatics/WebContent"

  val phoneBookService: PhoneBookService
  val contactService: ContactService

  implicit def optionMarshaller[T](implicit codec: GenCodec[T]): ToResponseMarshaller[Option[T]] =
    gencodecMarshaller[Option[T]](GenCodec.optionCodec(codec))

  implicit def gencodecMarshaller[T](implicit codec: GenCodec[T]): ToEntityMarshaller[T] =
    Marshaller.withFixedContentType(MediaTypes.`application/json`) { value =>
      HttpEntity(MediaTypes.`application/json`, JsonStringOutput.write(value))
    }

  implicit def gencodecUnmarshaller[T](implicit codec: GenCodec[T]): FromEntityUnmarshaller[T] =
    Unmarshaller.stringUnmarshaller.forContentTypes(MediaTypes.`application/json`).map{ data =>
      JsonStringInput.read[T](data)
    }

  private def completeIfNonEmpty[T](ctx: RequestContext)(opt: Option[T])(implicit rm: ToResponseMarshaller[T]) =
    opt match {
      case Some(v) => complete(v)(ctx)
      case None => complete(StatusCodes.NotFound)(ctx)
    }

  val route: Route = {
    pathPrefix("scripts"){
      getFromDirectory(s"$staticsDir/scripts")
    } ~
    pathPrefix("assets"){
      getFromDirectory(s"$staticsDir/assets")
    } ~
    pathPrefix("api") {
      pathPrefix("book") {
        pathPrefix(Segment) { segment =>
          val bookId = PhoneBookId(segment.toInt)
          pathPrefix("contacts") {
            pathPrefix("count") {
              get {
                
            entity(as[Contact]) { contact =>
              complete { contactService.create(contact) }
            }
          }
      }
    } ~ get {
      getFromFile(s"$staticsDir/index.html")
    }
  }
}

class PhoneBookWebService() extends PhoneBookWebServiceSpec {
  override val phoneBookService: PhoneBookService = InMemoryPhoneBookService
  override val contactService: ContactService = InMemoryContactService
} 
Example 89
Source File: ClusterBootstrap.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management.cluster.bootstrap

import java.util.concurrent.atomic.AtomicReference

import akka.AkkaVersion
import scala.concurrent.{ Future, Promise, TimeoutException }
import scala.concurrent.duration._

import akka.actor.ActorSystem
import akka.actor.ClassicActorSystemProvider
import akka.actor.ExtendedActorSystem
import akka.actor.Extension
import akka.actor.ExtensionId
import akka.actor.ExtensionIdProvider
import akka.annotation.InternalApi
import akka.cluster.Cluster
import akka.discovery.{ Discovery, ServiceDiscovery }
import akka.event.Logging
import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.server.Route
import akka.management.cluster.bootstrap.contactpoint.HttpClusterBootstrapRoutes
import akka.management.cluster.bootstrap.internal.BootstrapCoordinator
import akka.management.scaladsl.ManagementRouteProviderSettings
import akka.management.scaladsl.ManagementRouteProvider

final class ClusterBootstrap(implicit system: ExtendedActorSystem) extends Extension with ManagementRouteProvider {

  import ClusterBootstrap.Internal._
  import system.dispatcher

  private val log = Logging(system, classOf[ClusterBootstrap])

  private final val bootstrapStep = new AtomicReference[BootstrapStep](NotRunning)

  AkkaVersion.require("cluster-bootstrap", "2.5.27")

  val settings: ClusterBootstrapSettings = ClusterBootstrapSettings(system.settings.config, log)

  // used for initial discovery of contact points
  lazy val discovery: ServiceDiscovery =
    settings.contactPointDiscovery.discoveryMethod match {
      case "akka.discovery" =>
        val discovery = Discovery(system).discovery
        log.info("Bootstrap using default `akka.discovery` method: {}", Logging.simpleName(discovery))
        discovery

      case otherDiscoveryMechanism =>
        log.info("Bootstrap using `akka.discovery` method: {}", otherDiscoveryMechanism)
        Discovery(system).loadServiceDiscovery(otherDiscoveryMechanism)
    }

  private val joinDecider: JoinDecider = {
    system.dynamicAccess
      .createInstanceFor[JoinDecider](
        settings.joinDecider.implClass,
        List((classOf[ActorSystem], system), (classOf[ClusterBootstrapSettings], settings))
      )
      .get
  }

  private[this] val _selfContactPointUri: Promise[Uri] = Promise()

  override def routes(routeProviderSettings: ManagementRouteProviderSettings): Route = {
    log.info(s"Using self contact point address: ${routeProviderSettings.selfBaseUri}")
    this.setSelfContactPoint(routeProviderSettings.selfBaseUri)

    new HttpClusterBootstrapRoutes(settings).routes
  }

  def start(): Unit =
    if (Cluster(system).settings.SeedNodes.nonEmpty) {
      log.warning(
        "Application is configured with specific `akka.cluster.seed-nodes`: {}, bailing out of the bootstrap process! " +
        "If you want to use the automatic bootstrap mechanism, make sure to NOT set explicit seed nodes in the configuration. " +
        "This node will attempt to join the configured seed nodes.",
        Cluster(system).settings.SeedNodes.mkString("[", ", ", "]")
      )
    } else if (bootstrapStep.compareAndSet(NotRunning, Initializing)) {
      log.info("Initiating bootstrap procedure using {} method...", settings.contactPointDiscovery.discoveryMethod)

      ensureSelfContactPoint()
      val bootstrapProps = BootstrapCoordinator.props(discovery, joinDecider, settings)
      val bootstrap = system.systemActorOf(bootstrapProps, "bootstrapCoordinator")
      // Bootstrap already logs in several other execution points when it can't form a cluster, and why.
      selfContactPoint.foreach { uri =>
        bootstrap ! BootstrapCoordinator.Protocol.InitiateBootstrapping(uri)
      }
    } else log.warning("Bootstrap already initiated, yet start() method was called again. Ignoring.")

  
  private[bootstrap] object Internal {
    sealed trait BootstrapStep
    case object NotRunning extends BootstrapStep
    case object Initializing extends BootstrapStep
  }

} 
Example 90
Source File: HttpClusterBootstrapRoutes.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management.cluster.bootstrap.contactpoint

import scala.concurrent.duration._

import akka.actor.ActorSystem
import akka.cluster.Cluster
import akka.cluster.Member
import akka.event.Logging
import akka.event.LoggingAdapter
import akka.http.javadsl.server.directives.RouteAdapter
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.server.Route
import akka.management.cluster.bootstrap.ClusterBootstrapSettings
import akka.management.cluster.bootstrap.contactpoint.HttpBootstrapJsonProtocol.ClusterMember
import akka.management.cluster.bootstrap.contactpoint.HttpBootstrapJsonProtocol.SeedNodes

final class HttpClusterBootstrapRoutes(settings: ClusterBootstrapSettings) extends HttpBootstrapJsonProtocol {

  import akka.http.scaladsl.server.Directives._

  private def routeGetSeedNodes: Route = extractClientIP { clientIp =>
    extractActorSystem { implicit system =>
      import akka.cluster.MemberStatus
      val cluster = Cluster(system)

      def memberToClusterMember(m: Member): ClusterMember =
        ClusterMember(m.uniqueAddress.address, m.uniqueAddress.longUid, m.status.toString, m.roles)

      val state = cluster.state

      // TODO shuffle the members so in a big deployment nodes start joining different ones and not all the same?
      val members = state.members
        .diff(state.unreachable)
        .filter(m =>
          m.status == MemberStatus.up || m.status == MemberStatus.weaklyUp || m.status == MemberStatus.joining)
        .take(settings.contactPoint.httpMaxSeedNodesToExpose)
        .map(memberToClusterMember)

      val info = SeedNodes(cluster.selfMember.uniqueAddress.address, members)
      log.info(
        "Bootstrap request from {}: Contact Point returning {} seed-nodes [{}]",
        clientIp,
        members.size,
        members.map(_.node).mkString(", "))
      complete(info)
    }
  }

  
  def getRoutes: akka.http.javadsl.server.Route = RouteAdapter(routes)

  private def log(implicit sys: ActorSystem): LoggingAdapter =
    Logging(sys, classOf[HttpClusterBootstrapRoutes])

}

object ClusterBootstrapRequests {

  import akka.http.scaladsl.client.RequestBuilding._

  def bootstrapSeedNodes(baseUri: Uri): HttpRequest =
    Get(baseUri + "/bootstrap/seed-nodes")

} 
Example 91
Source File: HealthCheckRoutes.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management

import akka.actor.ExtendedActorSystem
import akka.annotation.InternalApi
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ PathMatchers, Route }
import akka.management.scaladsl.{ HealthChecks, ManagementRouteProvider, ManagementRouteProviderSettings }

import scala.util.{ Failure, Success, Try }


@InternalApi
private[akka] class HealthCheckRoutes(system: ExtendedActorSystem) extends ManagementRouteProvider {

  private val settings: HealthCheckSettings = HealthCheckSettings(
    system.settings.config.getConfig("akka.management.health-checks")
  )

  // exposed for testing
  protected val healthChecks = HealthChecks(system, settings)

  private val healthCheckResponse: Try[Either[String, Unit]] => Route = {
    case Success(Right(())) => complete(StatusCodes.OK)
    case Success(Left(failingChecks)) =>
      complete(StatusCodes.InternalServerError -> s"Not Healthy: $failingChecks")
    case Failure(t) =>
      complete(
        StatusCodes.InternalServerError -> s"Health Check Failed: ${t.getMessage}"
      )
  }

  override def routes(mrps: ManagementRouteProviderSettings): Route = {
    concat(
      path(PathMatchers.separateOnSlashes(settings.readinessPath)) {
        get {
          onComplete(healthChecks.readyResult())(healthCheckResponse)
        }
      },
      path(PathMatchers.separateOnSlashes(settings.livenessPath)) {
        get {
          onComplete(healthChecks.aliveResult())(healthCheckResponse)
        }
      }
    )
  }
} 
Example 92
Source File: ClusterHttpManagementRouteProvider.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management.cluster

import akka.actor.ClassicActorSystemProvider
import akka.actor.{ ActorSystem, ExtendedActorSystem, ExtensionId, ExtensionIdProvider }
import akka.cluster.Cluster
import akka.http.scaladsl.server.Route
import akka.management.cluster.scaladsl.ClusterHttpManagementRoutes
import akka.management.scaladsl.ManagementRouteProviderSettings
import akka.management.scaladsl.ManagementRouteProvider

object ClusterHttpManagementRouteProvider
    extends ExtensionId[ClusterHttpManagementRouteProvider]
    with ExtensionIdProvider {
  override def lookup: ClusterHttpManagementRouteProvider.type = ClusterHttpManagementRouteProvider

  override def get(system: ActorSystem): ClusterHttpManagementRouteProvider = super.get(system)

  override def get(system: ClassicActorSystemProvider): ClusterHttpManagementRouteProvider = super.get(system)

  override def createExtension(system: ExtendedActorSystem): ClusterHttpManagementRouteProvider =
    new ClusterHttpManagementRouteProvider(system)

}


  override def routes(routeProviderSettings: ManagementRouteProviderSettings): Route =
    if (routeProviderSettings.readOnly) {
      ClusterHttpManagementRoutes.readOnly(cluster)
    } else {
      ClusterHttpManagementRoutes(cluster)
    }

} 
Example 93
Source File: CompileOnlySpec.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package doc.akka.cluster.http.management

import akka.actor.ActorSystem
import akka.cluster.Cluster
import akka.http.scaladsl.server.Route
import akka.management.cluster.scaladsl.ClusterHttpManagementRoutes
import akka.management.scaladsl.AkkaManagement

object CompileOnlySpec {

  //#loading
  val system = ActorSystem()
  // Automatically loads Cluster Http Routes
  AkkaManagement(system).start()
  //#loading

  //#all
  val cluster = Cluster(system)
  val allRoutes: Route = ClusterHttpManagementRoutes(cluster)
  //#all

  //#read-only
  val readOnlyRoutes: Route = ClusterHttpManagementRoutes.readOnly(cluster)
  //#read-only
} 
Example 94
Source File: ReservationViewEndpoint.scala    From ddd-leaven-akka-v2   with MIT License 5 votes vote down vote up
package ecommerce.sales.app

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import ecommerce.sales.ReadEndpoint
import ecommerce.sales.view.ReservationDao
import org.json4s.Formats
import pl.newicom.dddd.view.sql.SqlViewStore
import slick.jdbc.JdbcProfile

import scala.concurrent.ExecutionContext

class ReservationViewEndpoint(implicit ec: ExecutionContext, profile: JdbcProfile, formats: Formats) extends ReadEndpoint {

  lazy val dao = new ReservationDao

  def route(viewStore: SqlViewStore): Route = {
    path("reservation" / "all") {
      get {
        complete {
          viewStore.run {
            dao.all
          }
        }
      }
    } ~
    path("reservation" / Segment) { id =>
      get {
        onSuccess(viewStore.run(dao.byId(id))) {
          case Some(res) => complete(res)
          case None => complete(StatusCodes.NotFound -> "unknown reservation")
        }
      }
    }

  }

} 
Example 95
Source File: ShipmentViewEndpoint.scala    From ddd-leaven-akka-v2   with MIT License 5 votes vote down vote up
package ecommerce.shipping.app

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import ecommerce.shipping.view.ShipmentDao
import ecommerce.shipping.ReadEndpoint
import org.json4s.Formats
import pl.newicom.dddd.view.sql.SqlViewStore

import scala.concurrent.ExecutionContext
import slick.jdbc.JdbcProfile

class ShipmentViewEndpoint(implicit val ec: ExecutionContext, profile: JdbcProfile, formats: Formats) extends ReadEndpoint {

  lazy val dao = new ShipmentDao

  def route(viewStore: SqlViewStore): Route = {
    path("shipment" / "all") {
      get {
        complete {
          viewStore.run {
            dao.all
          }
        }
      }
    } ~
    path("shipment" / Segment) { id =>
      get {
        onSuccess(viewStore.run(dao.byId(id))) {
          case Some(res) => complete(res)
          case None => complete(StatusCodes.NotFound -> "unknown shipment")
        }
      }
    } ~
    path("shipment" / "order" / Segment) { id =>
      get {
        onSuccess(viewStore.run(dao.byOrderId(id))) {
          case seq if seq.isEmpty =>
            complete(StatusCodes.NotFound -> "unknown order")
          case orders =>
            complete(orders)
        }
      }
    }

  }
} 
Example 96
Source File: AkkaHttpSupportSpec.scala    From borer   with Mozilla Public License 2.0 5 votes vote down vote up
package io.bullet.borer.site

import utest._

object AkkaHttpSupportSpec extends TestSuite {

  val tests = Tests {

    "example" - {

      //#example
      import akka.http.scaladsl.server.Route
      import akka.http.scaladsl.server.Directives._

      // custom model for request and response content
      final case class MyRequest(foo: String)
      final case class MyResponse(importantValue: Int)

      // borer encoders/decoders for the custom model above
      import io.bullet.borer.derivation.MapBasedCodecs._

      implicit val myRequestDecoder  = deriveCodec[MyRequest]
      implicit val myResponseEncoder = deriveCodec[MyResponse]

      // bring automatic (un) marshaller construction in scope
      import io.bullet.borer.compat.akkaHttp._

      // route that unmarshalls to `MyRequest` and marshals to `MyResponse`
      val route: Route =
        pathSingleSlash {
          post {
            entity(as[MyRequest]) { myRequest =>
              complete {
                MyResponse(myRequest.foo.length)
              }
            }
          }
        }
      //#example
    }
  }
} 
Example 97
Source File: ExtraDirectives.scala    From eclair   with Apache License 2.0 5 votes vote down vote up
package fr.acinq.eclair.api

import akka.http.scaladsl.marshalling.ToResponseMarshaller
import akka.http.scaladsl.model.StatusCodes.NotFound
import akka.http.scaladsl.model.{ContentTypes, HttpResponse}
import akka.http.scaladsl.server.{Directive1, Directives, MalformedFormFieldRejection, Route}
import fr.acinq.bitcoin.ByteVector32
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.ApiTypes.ChannelIdentifier
import fr.acinq.eclair.api.FormParamExtractors._
import fr.acinq.eclair.api.JsonSupport._
import fr.acinq.eclair.payment.PaymentRequest
import fr.acinq.eclair.{MilliSatoshi, ShortChannelId}

import scala.concurrent.Future
import scala.util.{Failure, Success}

trait ExtraDirectives extends Directives {

  // named and typed URL parameters used across several routes
  val shortChannelIdFormParam = "shortChannelId".as[ShortChannelId](shortChannelIdUnmarshaller)
  val shortChannelIdsFormParam = "shortChannelIds".as[List[ShortChannelId]](shortChannelIdsUnmarshaller)
  val channelIdFormParam = "channelId".as[ByteVector32](sha256HashUnmarshaller)
  val channelIdsFormParam = "channelIds".as[List[ByteVector32]](sha256HashesUnmarshaller)
  val nodeIdFormParam = "nodeId".as[PublicKey]
  val nodeIdsFormParam = "nodeIds".as[List[PublicKey]](pubkeyListUnmarshaller)
  val paymentHashFormParam = "paymentHash".as[ByteVector32](sha256HashUnmarshaller)
  val fromFormParam = "from".as[Long]
  val toFormParam = "to".as[Long]
  val amountMsatFormParam = "amountMsat".as[MilliSatoshi]
  val invoiceFormParam = "invoice".as[PaymentRequest]

  // custom directive to fail with HTTP 404 (and JSON response) if the element was not found
  def completeOrNotFound[T](fut: Future[Option[T]])(implicit marshaller: ToResponseMarshaller[T]): Route = onComplete(fut) {
    case Success(Some(t)) => complete(t)
    case Success(None) =>
      complete(HttpResponse(NotFound).withEntity(ContentTypes.`application/json`, serialization.writePretty(ErrorResponse("Not found"))))
    case Failure(_) => reject
  }

  def withChannelIdentifier: Directive1[ChannelIdentifier] = formFields(channelIdFormParam.?, shortChannelIdFormParam.?).tflatMap {
    case (Some(channelId), None) => provide(Left(channelId))
    case (None, Some(shortChannelId)) => provide(Right(shortChannelId))
    case _ => reject(MalformedFormFieldRejection("channelId/shortChannelId", "Must specify either the channelId or shortChannelId (not both)"))
  }

  def withChannelsIdentifier: Directive1[List[ChannelIdentifier]] = formFields(channelIdFormParam.?, channelIdsFormParam.?, shortChannelIdFormParam.?, shortChannelIdsFormParam.?).tflatMap {
    case (None, None, None, None) => reject(MalformedFormFieldRejection("channelId(s)/shortChannelId(s)", "Must specify channelId, channelIds, shortChannelId or shortChannelIds"))
    case (channelId_opt, channelIds_opt, shortChannelId_opt, shortChannelIds_opt) =>
      val channelId: List[ChannelIdentifier] = channelId_opt.map(cid => Left(cid)).toList
      val channelIds: List[ChannelIdentifier] = channelIds_opt.map(_.map(cid => Left(cid))).toList.flatten
      val shortChannelId: List[ChannelIdentifier] = shortChannelId_opt.map(scid => Right(scid)).toList
      val shortChannelIds: List[ChannelIdentifier] = shortChannelIds_opt.map(_.map(scid => Right(scid))).toList.flatten
      provide((channelId ++ channelIds ++ shortChannelId ++ shortChannelIds).distinct)
  }

} 
Example 98
Source File: Routing.scala    From akka-http-extensions   with Apache License 2.0 5 votes vote down vote up
package com.lonelyplanet.akka.http.extensions
import akka.actor.ActorSystem
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.lonelyplanet.akka.http.extensions.exceptions.ResourceNotFound

import scala.concurrent.Future

class Routing extends ExceptionHandling {
  implicit val system = ActorSystem("test")
  implicit val executionContext = system.dispatcher

  val route = Route.seal {
    path("") {
      get {
        complete {
          "ok"
        }
      }
    } ~ path("exception") {
      get {
        complete {
          Future {
            throw new RuntimeException("exception")
            "should not happen"
          }
        }
      }
    } ~ path("resource") {
      get {
        complete {
          Future {
            throw new ResourceNotFound("resource not found")
            "should not happen"
          }
        }
      }
    }
  }
} 
Example 99
Source File: ProgressRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import akka.NotUsed
import akka.actor.ActorRef
import akka.http.scaladsl.coding.Gzip
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.http.scaladsl.model.ws.TextMessage._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.stream.scaladsl._
import com.olegych.scastie.api._
import com.olegych.scastie.balancer._
import play.api.libs.json.Json

import scala.concurrent.Future
import scala.concurrent.duration.DurationInt

class ProgressRoutes(progressActor: ActorRef) {
  val routes: Route = encodeResponseWith(Gzip)(
    concat(
      snippetIdStart("progress-sse") { sid =>
        complete {
          progressSource(sid).map { progress =>
            ServerSentEvent(Json.stringify(Json.toJson(progress)))
          }
        }
      },
      snippetIdStart("progress-ws")(
        sid => handleWebSocketMessages(webSocket(sid))
      )
    )
  )

  private def progressSource(
      snippetId: SnippetId
  ): Source[SnippetProgress, NotUsed] = {
    Source
      .fromFuture((progressActor ? SubscribeProgress(snippetId))(1.second).mapTo[Source[SnippetProgress, NotUsed]])
      .flatMapConcat(identity)
  }

  private def webSocket(snippetId: SnippetId): Flow[ws.Message, ws.Message, _] = {
    def flow: Flow[String, SnippetProgress, NotUsed] = {
      val in = Flow[String].to(Sink.ignore)
      val out = progressSource(snippetId)
      Flow.fromSinkAndSource(in, out)
    }

    Flow[ws.Message]
      .mapAsync(1) {
        case Strict(c) => Future.successful(c)
        case e         => Future.failed(new Exception(e.toString))
      }
      .via(flow)
      .map(
        progress => ws.TextMessage.Strict(Json.stringify(Json.toJson(progress)))
      )
  }
} 
Example 100
Source File: ScalaLangRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import com.olegych.scastie.api._
import com.olegych.scastie.web.oauth2._

import com.olegych.scastie.balancer._

import akka.util.Timeout
import akka.actor.{ActorRef, ActorSystem}

import akka.http.scaladsl.model.StatusCodes.Created
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives._

import akka.pattern.ask

import scala.concurrent.duration.DurationInt

// temporary route for the scala-lang frontpage
class ScalaLangRoutes(
    dispatchActor: ActorRef,
    userDirectives: UserDirectives
)(implicit system: ActorSystem) {
  import system.dispatcher
  import userDirectives.optionalLogin

  implicit val timeout: Timeout = Timeout(5.seconds)

  // format: off
  val routes: Route =
    post(
      extractClientIP(remoteAddress =>
        optionalLogin(user =>
          path("scala-lang")(
            entity(as[String]) { code =>
              val inputs =
                InputsWithIpAndUser(
                  Inputs.default.copy(code = code),
                  UserTrace(
                    remoteAddress.toString,
                    None
                  )
                )

              complete(
                (dispatchActor ? RunSnippet(inputs))
                  .mapTo[SnippetId]
                  .map(
                    snippetId =>
                      (
                        Created,
                        snippetId.url
                    )
                  )
              )
            }
          )
        )
      )
    )
} 
Example 101
Source File: ScalaJsRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import com.olegych.scastie.api._

import akka.util.Timeout

import akka.pattern.ask
import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.coding.Gzip

import scala.concurrent.duration.DurationInt

//not used anymore
class ScalaJsRoutes(dispatchActor: ActorRef)(implicit system: ActorSystem) {
  import system.dispatcher

  implicit val timeout: Timeout = Timeout(1.seconds)

  val routes: Route =
    encodeResponseWith(Gzip)(
      concat(
        snippetIdEnd(Shared.scalaJsHttpPathPrefix, ScalaTarget.Js.targetFilename)(
          sid =>
            complete(
              (dispatchActor ? FetchScalaJs(sid))
                .mapTo[Option[FetchResultScalaJs]]
                .map(_.map(_.content))
          )
        ),
        snippetIdEnd(Shared.scalaJsHttpPathPrefix, ScalaTarget.Js.sourceFilename)(
          sid =>
            complete(
              (dispatchActor ? FetchScalaSource(sid))
                .mapTo[Option[FetchResultScalaSource]]
                .map(_.map(_.content))
          )
        ),
        snippetIdEnd(Shared.scalaJsHttpPathPrefix, ScalaTarget.Js.sourceMapFilename)(
          sid =>
            complete(
              (dispatchActor ? FetchScalaJsSourceMap(sid))
                .mapTo[Option[FetchResultScalaJsSourceMap]]
                .map(_.map(_.content))
          )
        )
      )
    )
} 
Example 102
Source File: FrontPageRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import akka.http.scaladsl.coding.{Gzip, NoCoding}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.olegych.scastie.api.{SnippetId, SnippetUserPart}
import com.olegych.scastie.util.Base64UUID

class FrontPageRoutes(production: Boolean) {

  private def index = getFromResource("public/index.html")

  private def embeddedResource(snippetId: SnippetId, theme: Option[String]): String = {
    val user = snippetId.user match {
      case Some(SnippetUserPart(login, update)) =>
        s"user: '$login', update: $update,"
      case None => ""
    }

    val themePart = theme match {
      case Some(t) => s"theme: '$t',"
      case None    => ""
    }

    val id = "id-" + Base64UUID.create

    val embeddedUrlBase =
      if (production) "https://scastie.scala-lang.org"
      else "http://localhost:9000"

    s"""|document.write("
        |<div id='$id'></div>
        |<script src='$embeddedUrlBase/embedded.js'></script>
        |<script>
        |window.addEventListener('load', function(event) {
        |  scastie.EmbeddedResource({
        |    $themePart
        |    base64UUID: '${snippetId.base64UUID}',
        |    $user
        |    injectId: '$id',
        |    serverUrl: '$embeddedUrlBase'
        |  });
        |});
        |</script>
        |");""".stripMargin.split("\n").map(_.trim).mkString("")
  }

  val routes: Route = encodeResponseWith(Gzip, NoCoding)(
    concat(
      get(
        concat(
          path("public" / "app.css")(
            getFromResource("public/app.css.gz")
          ),
          path("public" / "app.js")(
            getFromResource("public/app.js.gz")
          ),
          path("public" / "embedded.css")(
            getFromResource("public/embedded.css.gz")
          ),
          path("embedded.js")(
            getFromResource("public/embedded.js.gz")
          ),
          path("embedded.js.map")(
            getFromResource("public/embedded.js.map")
          ),
          path("public" / Remaining)(
            path => getFromResource("public/" + path)
          )
        )
      ),
      get(
        concat(
          pathSingleSlash(index),
          snippetId(_ => index),
          parameter("theme".?) { theme =>
            snippetIdExtension(".js") { sid =>
              complete(embeddedResource(sid, theme))
            }
          },
          index,
        )
      )
    )
  )
} 
Example 103
Source File: StatusRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import akka.NotUsed
import akka.actor.ActorRef
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.http.scaladsl.model.ws.TextMessage._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Route, _}
import akka.pattern.ask
import akka.stream.scaladsl._
import com.olegych.scastie.api._
import com.olegych.scastie.balancer._
import com.olegych.scastie.web.oauth2.UserDirectives
import play.api.libs.json.Json

import scala.concurrent.duration.DurationInt
import scala.concurrent.{ExecutionContext, Future}

class StatusRoutes(statusActor: ActorRef, userDirectives: UserDirectives)(implicit ec: ExecutionContext) {

  val isAdminUser: Directive1[Boolean] =
    userDirectives.optionalLogin.map(
      user => user.exists(_.isAdmin)
    )

  val routes: Route =
    isAdminUser { isAdmin =>
      concat(
        path("status-sse")(
          complete(
            statusSource(isAdmin).map { progress =>
              ServerSentEvent(
                Json.stringify(Json.toJson(progress))
              )
            }
          )
        ),
        path("status-ws")(
          handleWebSocketMessages(webSocketProgress(isAdmin))
        )
      )
    }

  private def statusSource(isAdmin: Boolean) = {
    def hideTask(progress: StatusProgress): StatusProgress =
      if (isAdmin) progress
      else
        progress match {
          case StatusProgress.Sbt(runners) =>
            // Hide the task Queue for non admin users,
            // they will only see the runner count
            StatusProgress.Sbt(
              runners.map(_.copy(tasks = Vector()))
            )

          case _ =>
            progress
        }
    Source
      .fromFuture((statusActor ? SubscribeStatus)(2.seconds).mapTo[Source[StatusProgress, NotUsed]])
      .flatMapConcat(s => s.map(hideTask))
  }

  private def webSocketProgress(
      isAdmin: Boolean
  ): Flow[ws.Message, ws.Message, _] = {
    def flow: Flow[String, StatusProgress, NotUsed] = {
      val in = Flow[String].to(Sink.ignore)
      val out = statusSource(isAdmin)
      Flow.fromSinkAndSource(in, out)
    }

    Flow[ws.Message]
      .mapAsync(1) {
        case Strict(c) => Future.successful(c)
        case e => Future.failed(new Exception(e.toString))
      }
      .via(flow)
      .map(
        progress => ws.TextMessage.Strict(Json.stringify(Json.toJson(progress)))
      )
  }
} 
Example 104
Source File: OAuth2Routes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie
package web
package routes

import oauth2._

import com.softwaremill.session.SessionDirectives._
import com.softwaremill.session.SessionOptions._
import com.softwaremill.session.CsrfDirectives._
import com.softwaremill.session.CsrfOptions._

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.Uri.Query
import akka.http.scaladsl.model.StatusCodes.TemporaryRedirect
import akka.http.scaladsl.model.headers.Referer
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

import scala.concurrent.ExecutionContext

class OAuth2Routes(github: Github, session: GithubUserSession)(
    implicit val executionContext: ExecutionContext
) {
  import session._

  val routes: Route =
    get(
      concat(
        path("login") {
          parameter("home".?)(
            home =>
              optionalHeaderValueByType[Referer](()) { referrer =>
                redirect(
                  Uri("https://github.com/login/oauth/authorize").withQuery(
                    Query(
                      "client_id" -> github.clientId,
                      "state" -> {
                        val homeUri = "/"
                        if (home.isDefined) homeUri
                        else referrer.map(_.value).getOrElse(homeUri)
                      }
                    )
                  ),
                  TemporaryRedirect
                )
            }
          )
        },
        path("logout") {
          headerValueByType[Referer](()) { referrer =>
            requiredSession(refreshable, usingCookies) { _ =>
              invalidateSession(refreshable, usingCookies) { ctx =>
                ctx.complete(
                  HttpResponse(
                    status = TemporaryRedirect,
                    headers = headers.Location(Uri(referrer.value)) :: Nil,
                    entity = HttpEntity.Empty
                  )
                )
              }
            }
          }
        },
        pathPrefix("callback") {
          pathEnd {
            parameters(("code", "state".?)) { (code, state) =>
              onSuccess(github.getUserWithOauth2(code)) { user =>
                setSession(refreshable, usingCookies, session.addUser(user)) {
                  setNewCsrfToken(checkHeader) { ctx =>
                    ctx.complete(
                      HttpResponse(
                        status = TemporaryRedirect,
                        headers = headers
                          .Location(Uri(state.getOrElse("/"))) :: Nil,
                        entity = HttpEntity.Empty
                      )
                    )
                  }
                }
              }
            }
          }
        }
      )
    )
} 
Example 105
Source File: ApiRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.coding.Gzip
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Directive1, Route}
import com.olegych.scastie.api._
import com.olegych.scastie.web._
import com.olegych.scastie.web.oauth2._

class ApiRoutes(
    dispatchActor: ActorRef,
    userDirectives: UserDirectives
)(implicit system: ActorSystem)
    extends PlayJsonSupport {

  import play.api.libs.json._
  import system.dispatcher
  import userDirectives.optionalLogin
  implicit val readsInputs: Reads[Inputs] = Json.reads[Inputs]

  val withRestApiServer: Directive1[RestApiServer] =
    (extractClientIP & optionalLogin).tmap {
      case (remoteAddress, user) =>
        new RestApiServer(dispatchActor, remoteAddress, user)
    }

  val routes: Route =
    withRestApiServer(
      server =>
        concat(
          post(
            concat(
              path("run")(
                entity(as[Inputs])(inputs => complete(server.run(inputs)))
              ),
              path("save")(
                entity(as[Inputs])(inputs => complete(server.save(inputs)))
              ),
              path("update")(
                entity(as[EditInputs])(
                  editInputs => complete(server.update(editInputs))
                )
              ),
              path("fork")(
                entity(as[EditInputs])(
                  editInputs => complete(server.fork(editInputs))
                )
              ),
              path("delete")(
                entity(as[SnippetId])(
                  snippetId => complete(server.delete(snippetId))
                )
              ),
              path("format")(
                entity(as[FormatRequest])(
                  request => complete(server.format(request))
                )
              )
            )
          ),
          encodeResponseWith(Gzip)(
            get(
              concat(
                snippetIdStart("snippets")(
                  sid => complete(server.fetch(sid))
                ),
                path("old-snippets" / IntNumber)(
                  id => complete(server.fetchOld(id))
                ),
                path("user" / "settings")(
                  complete(server.fetchUser())
                ),
                path("user" / "snippets")(
                  complete(server.fetchUserSnippets())
                )
              )
            )
          )
      )
    )
} 
Example 106
Source File: DownloadRoutes.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web.routes

import com.olegych.scastie.balancer.DownloadSnippet

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

import akka.actor.ActorRef
import akka.pattern.ask

import java.nio.file.Path

import akka.util.Timeout
import scala.concurrent.duration.DurationInt

class DownloadRoutes(dispatchActor: ActorRef) {
  implicit val timeout = Timeout(5.seconds)

  val routes: Route =
    get {
      snippetIdStart("download")(
        sid =>
          onSuccess((dispatchActor ? DownloadSnippet(sid)).mapTo[Option[Path]]) {
            case Some(path) =>
              getFromFile(path.toFile)
            case None =>
              throw new Exception(
                s"Can't serve project ${sid.base64UUID} to user ${sid.user.getOrElse("anon")}"
              )
        }
      )
    }
} 
Example 107
Source File: package.scala    From scastie   with Apache License 2.0 5 votes vote down vote up
package com.olegych.scastie.web

import com.olegych.scastie.api._

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{PathMatcher, Route}

package object routes {
  def snippetIdStart(matcherStart: String)(f: SnippetId => Route): Route =
    snippetIdBase(
      matcherStart / _,
      matcherStart / _
    )(f)

  def snippetId(f: SnippetId => Route): Route =
    snippetIdBase(
      p => p,
      p => p
    )(f)

  def snippetIdEnd(matcherStart: String, matcherEnd: String)(f: SnippetId => Route): Route =
    snippetIdBase(
      matcherStart / _ / matcherEnd,
      matcherStart / _ / matcherEnd
    )(f)

  def snippetIdExtension(extension: String)(f: SnippetId => Route): Route =
    snippetIdBase(
      _ ~ extension,
      _ ~ extension
    )(f)

  private val uuidMatcher = PathMatcher("[A-Za-z0-9]{22}".r)

  private def snippetIdBase(
      fp1: PathMatcher[Tuple1[String]] => PathMatcher[Tuple1[String]],
      fp2: PathMatcher[(String, String, Option[Int])] => PathMatcher[
        (String, String, Option[Int])
      ]
  )(f: SnippetId => Route): Route = {

    concat(
      path(fp1(uuidMatcher) ~ Slash.?)(uuid => f(SnippetId(uuid, None))),
      path(fp2(Segment / uuidMatcher ~ (Slash ~ IntNumber).?) ~ Slash.?)(
        (user, uuid, update) => f(SnippetId(uuid, Some(SnippetUserPart(user, update.getOrElse(0)))))
      )
    )
  }
} 
Example 108
Source File: AdminRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.index.{OrganizationCache, ProjectCache}
import ch.epfl.bluebrain.nexus.admin.organizations.Organizations
import ch.epfl.bluebrain.nexus.admin.projects.Projects
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.EventRoutes
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.{HttpConfig, PaginationConfig, PersistenceConfig}
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

object AdminRoutes {

  
  final def apply(
      orgs: Organizations[Task],
      projects: Projects[Task],
      orgCache: OrganizationCache[Task],
      projCache: ProjectCache[Task],
      acls: Acls[Task],
      realms: Realms[Task]
  )(implicit
      as: ActorSystem,
      cfg: ServiceConfig
  ): Route = {
    implicit val hc: HttpConfig        = cfg.http
    implicit val pc: PersistenceConfig = cfg.persistence
    implicit val pgc: PaginationConfig = cfg.pagination

    val eventsRoutes  = new EventRoutes(acls, realms).routes
    val orgRoutes     = new OrganizationRoutes(orgs, orgCache, acls, realms).routes
    val projectRoutes = new ProjectRoutes(projects, orgCache, projCache, acls, realms).routes

    pathPrefix(cfg.http.prefix) {
      eventsRoutes ~ orgRoutes ~ projectRoutes
    }
  }
} 
Example 109
Source File: StaticResourceRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.http.routes

import java.util.regex.Pattern.quote

import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport._
import ch.epfl.bluebrain.nexus.commons.http.directives.PrefixDirectives
import io.circe.Json
import io.circe.parser.parse

import scala.io.Source


class StaticResourceRoutes(resourcePaths: Map[String, String], prefix: String, baseUri: Uri) extends PrefixDirectives {

  private def contentOf(file: String): String = {
    val source   = Source.fromInputStream(getClass.getResourceAsStream(file))
    val contents = source.mkString
    source.close()
    contents
  }

  private def contentOf(file: String, replacements: Map[String, String]): String =
    replacements.foldLeft(contentOf(file)) {
      case (value, (regex, replacement)) => value.replaceAll(regex, replacement)
    }

  private val baseReplacement: Map[String, String] = Map(quote("{{base}}") -> baseUri.toString)

  private lazy val resources: Map[String, Json] =
    resourcePaths.view
      .mapValues { resource => parse(contentOf(resource, baseReplacement)).toOption }
      .flatMap {
        case (key, value) =>
          value match {
            case Some(v) => Some((key, v))
            case None    => None
          }
      }
      .toMap

  def routes: Route =
    uriPrefix(baseUri) {
      (get & pathPrefix(prefix)) {
        extractUnmatchedPath { resourcePath =>
          resources.get(resourcePath.toString) match {
            case Some(json) => complete(json)
            case None       => reject
          }
        }
      }
    }

} 
Example 110
Source File: EventRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.{Organization, Project}
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class EventRoutes(acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
    override val as: ActorSystem,
    override val config: ServiceConfig
) extends AuthDirectives(acls, realms)
    with EventCommonRoutes {

  private val read: Permission = Permission.unsafe("resources/read")

  def routes(project: Project): Route = {

    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/resources/{org}/{project}/events") {
        authorizeFor(project.organizationLabel / project.label, read)(caller) {
          complete(source(s"project=${project.uuid}", offset))
        }
      }
    }
  }

  def routes(org: Organization): Route =
    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/resources/{org}/events") {
        authorizeFor(/ + org.label, read)(caller) {
          complete(source(s"org=${org.uuid}", offset))
        }
      }
    }
} 
Example 111
Source File: TagRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.Project
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.config.Contexts.tagCtxUri
import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources._
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import io.circe.syntax._
import io.circe.{Encoder, Json}
import kamon.Kamon
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class TagRoutes private[routes] (
    resourceType: String,
    tags: Tags[Task],
    acls: Acls[Task],
    realms: Realms[Task],
    schema: Ref,
    write: Permission
)(implicit
    caller: Caller,
    project: Project,
    config: ServiceConfig
) extends AuthDirectives(acls, realms) {

  private val projectPath               = project.organizationLabel / project.label
  implicit private val subject: Subject = caller.subject

  
  def routes(id: AbsoluteIri): Route =
    // Consume the tag segment
    pathPrefix("tags") {
      concat(
        // Create tag
        (post & parameter("rev".as[Long]) & pathEndOrSingleSlash) { rev =>
          operationName(opName) {
            (authorizeFor(projectPath, write) & projectNotDeprecated) {
              entity(as[Json]) { source =>
                Kamon.currentSpan().tag("resource.operation", "create")
                complete(tags.create(Id(project.ref, id), rev, source, schema).value.runWithStatus(Created))
              }
            }
          }
        },
        // Fetch a tag
        (get & projectNotDeprecated & pathEndOrSingleSlash) {
          operationName(opName) {
            authorizeFor(projectPath, read)(caller) {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(tags.fetch(Id(project.ref, id), rev, schema).value.runWithStatus(OK))
                case _         => complete(tags.fetch(Id(project.ref, id), schema).value.runWithStatus(OK))
              }
            }
          }
        }
      )
    }

  implicit private def tagsEncoder: Encoder[TagSet] =
    Encoder.instance(tags => Json.obj("tags" -> Json.arr(tags.map(_.asJson).toSeq: _*)).addContext(tagCtxUri))

  private def opName: String                        =
    resourceType match {
      case "resources" => s"/${config.http.prefix}/resources/{org}/{project}/{schemaId}/{id}/tags"
      case _           => s"/${config.http.prefix}/$resourceType/{org}/{project}/{id}/tags"
    }
} 
Example 112
Source File: ArchiveRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import akka.http.scaladsl.model.headers.Accept
import akka.http.scaladsl.model.{HttpEntity, MediaTypes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.Project
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Caller
import ch.epfl.bluebrain.nexus.iam.types.Identity.Subject
import ch.epfl.bluebrain.nexus.kg.KgError.{InvalidOutputFormat, UnacceptedResponseContentType}
import ch.epfl.bluebrain.nexus.kg.archives.Archive._
import ch.epfl.bluebrain.nexus.kg.directives.PathDirectives._
import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._
import ch.epfl.bluebrain.nexus.kg.directives.QueryDirectives.outputFormat
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources._
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.Tar
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import io.circe.Json
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class ArchiveRoutes private[routes] (archives: Archives[Task], acls: Acls[Task], realms: Realms[Task])(implicit
    project: Project,
    caller: Caller,
    config: ServiceConfig
) extends AuthDirectives(acls, realms) {

  private val responseType              = MediaTypes.`application/x-tar`
  private val projectPath               = project.organizationLabel / project.label
  implicit private val subject: Subject = caller.subject

  
  def routes(id: AbsoluteIri): Route = {
    val resId = Id(project.ref, id)
    concat(
      // Create archive
      (put & pathEndOrSingleSlash) {
        operationName(s"/${config.http.prefix}/archives/{org}/{project}/{id}") {
          (authorizeFor(projectPath, write) & projectNotDeprecated) {
            entity(as[Json]) { source =>
              complete(archives.create(resId, source).value.runWithStatus(Created))
            }
          }
        }
      },
      // Fetch archive
      (get & outputFormat(strict = true, Tar) & pathEndOrSingleSlash) {
        case Tar                           => getArchive(resId)
        case format: NonBinaryOutputFormat => getResource(resId)(format)
        case other                         => failWith(InvalidOutputFormat(other.toString))

      }
    )
  }

  private def getResource(resId: ResId)(implicit format: NonBinaryOutputFormat): Route =
    completeWithFormat(archives.fetch(resId).value.runWithStatus(OK))

  private def getArchive(resId: ResId): Route = {
    (parameter("ignoreNotFound".as[Boolean] ? false) & extractCallerAcls(anyProject)) { (ignoreNotFound, acls) =>
      onSuccess(archives.fetchArchive(resId, ignoreNotFound)(acls, caller).value.runToFuture) {
        case Right(source) =>
          headerValueByType[Accept](()) { accept =>
            if (accept.mediaRanges.exists(_.matches(responseType)))
              complete(HttpEntity(responseType, source))
            else
              failWith(
                UnacceptedResponseContentType(
                  s"File Media Type '$responseType' does not match the Accept header value '${accept.mediaRanges.mkString(", ")}'"
                )
              )
          }
        case Left(err)     => complete(err)
      }
    }
  }
} 
Example 113
Source File: GlobalEventRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.persistence.TaggingAdapter
import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class GlobalEventRoutes(acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
    override val as: ActorSystem,
    override val config: ServiceConfig
) extends AuthDirectives(acls, realms)
    with EventCommonRoutes {

  private val read: Permission = Permission.unsafe("events/read")

  def routes: Route =
    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/events") {
        authorizeFor(permission = read)(caller) {
          complete(source(TaggingAdapter.EventTag, offset))
        }
      }
    }
} 
Example 114
Source File: package.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg

import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.server.{MalformedQueryParamRejection, Route}
import cats.Functor
import cats.data.{EitherT, OptionT}
import cats.instances.future._
import ch.epfl.bluebrain.nexus.iam.types.Permission
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources.Rejection.NotFound.notFound
import ch.epfl.bluebrain.nexus.kg.resources.{Ref, Rejection, ResourceV}
import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.{DOT, Triples}
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import monix.execution.Scheduler.Implicits.global

import scala.concurrent.Future

package object routes {

  private[routes] def completeWithFormat(
      fetched: Future[Either[Rejection, (StatusCode, ResourceV)]]
  )(implicit format: NonBinaryOutputFormat): Route =
    completeWithFormat(EitherT(fetched))

  private def completeWithFormat(
      fetched: EitherT[Future, Rejection, (StatusCode, ResourceV)]
  )(implicit format: NonBinaryOutputFormat): Route =
    format match {
      case f: JsonLDOutputFormat =>
        implicit val format = f
        complete(fetched.value)
      case Triples               =>
        implicit val format = Triples
        complete(fetched.map { case (status, resource) => status -> resource.value.graph.ntriples }.value)
      case DOT                   =>
        implicit val format = DOT
        complete(fetched.map { case (status, resource) => status -> resource.value.graph.dot() }.value)
    }

  private[routes] val read: Permission = Permission.unsafe("resources/read")

  private[routes] val schemaError =
    MalformedQueryParamRejection("schema", "The provided schema does not match the schema on the Uri")

  implicit private[routes] class FOptionSyntax[F[_], A](private val fOpt: F[Option[A]]) extends AnyVal {
    def toNotFound(id: AbsoluteIri)(implicit F: Functor[F]): EitherT[F, Rejection, A] =
      OptionT(fOpt).toRight(notFound(Ref(id)))
  }
} 
Example 115
Source File: IamRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.{HttpConfig, PersistenceConfig}
import monix.eval.Task

object IamRoutes {

  final def apply(
      acls: Acls[Task],
      realms: Realms[Task],
      perms: Permissions[Task]
  )(implicit as: ActorSystem, cfg: ServiceConfig): Route = {
    implicit val hc: HttpConfig        = cfg.http
    implicit val pc: PersistenceConfig = cfg.persistence

    val eventsRoutes = new EventRoutes(acls, realms).routes
    val idsRoutes    = new IdentitiesRoutes(acls, realms).routes
    val permsRoutes  = new PermissionsRoutes(perms, acls, realms).routes
    val realmsRoutes = new RealmsRoutes(acls, realms).routes
    val aclsRoutes   = new AclsRoutes(acls, realms).routes

    pathPrefix(cfg.http.prefix) {
      eventsRoutes ~ aclsRoutes ~ permsRoutes ~ realmsRoutes ~ idsRoutes
    }
  }
} 
Example 116
Source File: PermissionsRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.Permission
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import ch.epfl.bluebrain.nexus.service.marshallers.instances._
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], acls: Acls[Task], realms: Realms[Task])(implicit
    http: HttpConfig
) extends AuthDirectives(acls, realms) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        extractCaller { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _            => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev => complete(permissions.delete(rev).runToFuture) }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set)   =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _             =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  sealed private[routes] trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe          = hc.get[String]("@type").getOrElse("Replace")
          patch       <- tpe match {
                           case "Replace"  => Right(Replace(permissions))
                           case "Append"   => Right(Append(permissions))
                           case "Subtract" => Right(Subtract(permissions))
                           case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
                         }
        } yield patch
      }
  }

} 
Example 117
Source File: IdentitiesRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Caller.JsonLd._
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.marshallers.instances._
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class IdentitiesRoutes(acls: Acls[Task], realms: Realms[Task])(implicit http: HttpConfig)
    extends AuthDirectives(acls, realms) {

  def routes: Route = {
    (pathPrefix("identities") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/identities") {
        (extractCaller & get) { caller =>
          complete(caller)
        }
      }
    }
  }
} 
Example 118
Source File: QueryDirectivesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.directives

import java.net.URLEncoder
import java.util.UUID

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives.{complete, get}
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.admin.routes.SearchParams
import ch.epfl.bluebrain.nexus.admin.routes.SearchParams.Field
import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.config.Settings
import ch.epfl.bluebrain.nexus.service.routes.Routes
import ch.epfl.bluebrain.nexus.util.EitherValues
import io.circe.generic.auto._
import org.mockito.IdiomaticMockito
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class QueryDirectivesSpec
    extends AnyWordSpecLike
    with ScalatestRouteTest
    with Matchers
    with ScalaFutures
    with EitherValues
    with IdiomaticMockito {

  private def genIri: AbsoluteIri              = url"http://nexus.example.com/${UUID.randomUUID()}"
  private def encode(url: AbsoluteIri): String = URLEncoder.encode(url.asString, "UTF-8")
  private val config                           = Settings(system).serviceConfig
  implicit private val http: HttpConfig        = config.http

  private def routes(inner: Route): Route =
    Routes.wrap(inner)

  "Query directives" should {

    "handle query params" in {
      val createdBy     = genIri
      val updatedBy     = genIri
      val type1         = genIri
      val type2         = genIri
      def projectParams =
        Routes.wrap(
          (get & QueryDirectives.searchParamsProjects) { params => complete(StatusCodes.OK -> params) }
        )

      Get("/") ~> routes(projectParams) ~> check {
        responseAs[SearchParams] shouldEqual SearchParams.empty
      }

      Get(
        s"/?rev=1&deprecated=true&label=myLabel&type=${encode(type1)}&type=${encode(type2)}&createdBy=${encode(createdBy)}&updatedBy=${encode(updatedBy)}"
      ) ~> routes(projectParams) ~> check {
        responseAs[SearchParams] shouldEqual
          SearchParams(
            rev = Some(1L),
            deprecated = Some(true),
            projectLabel = Some(Field("myLabel", exactMatch = false)),
            types = Set(type1, type2),
            createdBy = Some(createdBy),
            updatedBy = Some(updatedBy)
          )

      }
    }
  }
} 
Example 119
Source File: RealmDirectivesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.directives

import java.net.URLEncoder

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport._
import ch.epfl.bluebrain.nexus.iam.directives.RealmDirectives._
import ch.epfl.bluebrain.nexus.iam.routes.SearchParams
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.util.EitherValues
import io.circe.generic.auto._
import org.mockito.IdiomaticMockito
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class RealmDirectivesSpec
    extends AnyWordSpecLike
    with ScalatestRouteTest
    with Matchers
    with ScalaFutures
    with EitherValues
    with IdiomaticMockito {

  private def route: Route = {
    (get & searchParams) { params => complete(params) }
  }

  private def encode(s: AbsoluteIri) = URLEncoder.encode(s.asString, "UTF-8")

  "Realm directives" should {
    "return query params" in {
      val createdBy: AbsoluteIri = url"http://example.com/created"
      val updatedBy: AbsoluteIri = url"http://example.com/updated"
      val tpe: AbsoluteIri       = url"http://example.com/tpe"
      val tpe2: AbsoluteIri      = url"http://example.com/tpe2"
      Get(
        s"/?rev=2&deprecated=true&type=${encode(tpe)}&type=${encode(tpe2)}&createdBy=${encode(createdBy)}&updatedBy=${encode(updatedBy)}"
      ) ~> route ~> check {
        responseAs[SearchParams] shouldEqual SearchParams(
          Some(true),
          Some(2L),
          Some(createdBy),
          Some(updatedBy),
          Set(tpe, tpe2)
        )
      }
    }
  }

} 
Example 120
Source File: Routes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage.routes

import akka.http.scaladsl.model.headers.{`WWW-Authenticate`, HttpChallenges}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route}
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.Caller
import ch.epfl.bluebrain.nexus.storage.StorageError._
import ch.epfl.bluebrain.nexus.storage.config.AppConfig
import ch.epfl.bluebrain.nexus.storage.config.AppConfig._
import ch.epfl.bluebrain.nexus.storage.routes.AuthDirectives._
import ch.epfl.bluebrain.nexus.storage.routes.PrefixDirectives._
import ch.epfl.bluebrain.nexus.storage.routes.instances._
import ch.epfl.bluebrain.nexus.storage.{AkkaSource, IamIdentitiesClient, Rejection, StorageError, Storages}
import com.typesafe.scalalogging.Logger
import monix.eval.Task

import scala.util.control.NonFatal

object Routes {

  private[this] val logger = Logger[this.type]

  
  def apply(
      storages: Storages[Task, AkkaSource]
  )(implicit config: AppConfig, identities: IamIdentitiesClient[Task]): Route =
    //TODO: Fetch Bearer token and verify identity
    wrap {
      concat(
        AppInfoRoutes(config.description).routes,
        (pathPrefix(config.http.prefix) & extractToken) { implicit token =>
          extractCaller.apply {
            case Caller(config.subject.subjectValue, _) => StorageRoutes(storages).routes
            case _                                      => failWith(AuthenticationFailed)
          }
        }
      )
    }

} 
Example 121
Source File: Main.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import java.nio.file.Paths
import java.time.Clock

import akka.actor.ActorSystem
import akka.event.{Logging, LoggingAdapter}
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import cats.effect.Effect
import ch.epfl.bluebrain.nexus.storage.Storages.DiskStorage
import ch.epfl.bluebrain.nexus.storage.attributes.AttributesCache
import ch.epfl.bluebrain.nexus.storage.config.{AppConfig, Settings}
import ch.epfl.bluebrain.nexus.storage.config.AppConfig._
import ch.epfl.bluebrain.nexus.storage.routes.Routes
import com.typesafe.config.{Config, ConfigFactory}
import kamon.Kamon
import monix.eval.Task
import monix.execution.Scheduler

import scala.concurrent.duration._
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.util.{Failure, Success}

//noinspection TypeAnnotation
// $COVERAGE-OFF$
object Main {

  def loadConfig(): Config = {
    val cfg = sys.env.get("STORAGE_CONFIG_FILE") orElse sys.props.get("storage.config.file") map { str =>
      val file = Paths.get(str).toAbsolutePath.toFile
      ConfigFactory.parseFile(file)
    } getOrElse ConfigFactory.empty()
    (cfg withFallback ConfigFactory.load()).resolve()
  }

  def setupMonitoring(config: Config): Unit = {
    if (sys.env.getOrElse("KAMON_ENABLED", "false").toBoolean) {
      Kamon.reconfigure(config)
      Kamon.loadModules()
    }
  }

  def shutdownMonitoring(): Unit = {
    if (sys.env.getOrElse("KAMON_ENABLED", "false").toBoolean) {
      Await.result(Kamon.stopModules(), 10.seconds)
    }
  }

  @SuppressWarnings(Array("UnusedMethodParameter"))
  def main(args: Array[String]): Unit = {
    val config = loadConfig()
    setupMonitoring(config)

    implicit val appConfig: AppConfig = Settings(config).appConfig

    implicit val as: ActorSystem                          = ActorSystem(appConfig.description.fullName, config)
    implicit val ec: ExecutionContext                     = as.dispatcher
    implicit val eff: Effect[Task]                        = Task.catsEffect(Scheduler.global)
    implicit val iamIdentities: IamIdentitiesClient[Task] = new IamIdentitiesClient[Task](appConfig.iam)
    implicit val timeout                                  = Timeout(1.minute)
    implicit val clock                                    = Clock.systemUTC

    val storages: Storages[Task, AkkaSource] =
      new DiskStorage(appConfig.storage, appConfig.digest, AttributesCache[Task, AkkaSource])

    val logger: LoggingAdapter = Logging(as, getClass)

    logger.info("==== Cluster is Live ====")
    val routes: Route = Routes(storages)

    val httpBinding: Future[Http.ServerBinding] = {
      Http().bindAndHandle(routes, appConfig.http.interface, appConfig.http.port)
    }
    httpBinding onComplete {
      case Success(binding) =>
        logger.info(s"Bound to ${binding.localAddress.getHostString}: ${binding.localAddress.getPort}")
      case Failure(th)      =>
        logger.error(th, "Failed to perform an http binding on {}:{}", appConfig.http.interface, appConfig.http.port)
        Await.result(as.terminate(), 10.seconds)
    }

    as.registerOnTermination {
      shutdownMonitoring()
    }
    // attempt to leave the cluster before shutting down
    val _ = sys.addShutdownHook {
      Await.result(as.terminate().map(_ => ()), 10.seconds)
    }
  }
}
// $COVERAGE-ON$ 
Example 122
Source File: AppInfoRoutesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage.routes

import java.util.regex.Pattern.quote

import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.storage.config.{AppConfig, Settings}
import ch.epfl.bluebrain.nexus.storage.routes.instances._
import ch.epfl.bluebrain.nexus.storage.utils.Resources
import ch.epfl.bluebrain.nexus.storage.{AkkaSource, IamIdentitiesClient, Storages}
import io.circe.Json
import monix.eval.Task
import org.mockito.IdiomaticMockito
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class AppInfoRoutesSpec
    extends AnyWordSpecLike
    with Matchers
    with ScalatestRouteTest
    with IdiomaticMockito
    with Resources {

  "the app info routes" should {

    implicit val config: AppConfig                        = Settings(system).appConfig
    implicit val iamIdentities: IamIdentitiesClient[Task] = mock[IamIdentitiesClient[Task]]
    val route: Route                                      = Routes(mock[Storages[Task, AkkaSource]])

    "return application information" in {
      Get("/") ~> route ~> check {
        status shouldEqual OK
        responseAs[Json] shouldEqual
          jsonContentOf("/app-info.json", Map(quote("{version}") -> config.description.version))
      }
    }
  }
} 
Example 123
Source File: PlatformDiscovery.scala    From Conseil   with Apache License 2.0 5 votes vote down vote up
package tech.cryptonomic.conseil.api.routes.platform.discovery

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.typesafe.scalalogging.LazyLogging
import endpoints.akkahttp
import endpoints.algebra.Documentation
import tech.cryptonomic.conseil.api.metadata.MetadataService
import tech.cryptonomic.conseil.common.generic.chain.DataTypes.AttributesValidationError
import tech.cryptonomic.conseil.common.metadata.{EntityPath, NetworkPath, PlatformPath}


  val route: Route =
    concat(
      platformsRoute,
      networksRoute,
      entitiesRoute,
      attributesRoute,
      attributesValuesRoute,
      attributesValuesWithFilterRoute
    )

  override def validatedAttributes[A](
      response: A => Route,
      invalidDocs: Documentation
  ): Either[List[AttributesValidationError], A] => Route = {
    case Left(errors) =>
      complete(StatusCodes.BadRequest -> s"Errors: \n${errors.mkString("\n")}")
    case Right(success) =>
      response(success)
  }
} 
Example 124
Source File: MyResource.scala    From quiz-management-service   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.quiz.management.routing

import akka.http.scaladsl.marshalling.{ToResponseMarshaller, ToResponseMarshallable}

import scala.concurrent.{ExecutionContext, Future}
import akka.http.scaladsl.model.headers.Location
import akka.http.scaladsl.server.{Directives, Route}

import com.danielasfregola.quiz.management.serializers.JsonSupport

trait MyResource extends Directives with JsonSupport {

  implicit def executionContext: ExecutionContext

  def completeWithLocationHeader[T](resourceId: Future[Option[T]], ifDefinedStatus: Int, ifEmptyStatus: Int): Route =
    onSuccess(resourceId) {
      case Some(t) => completeWithLocationHeader(ifDefinedStatus, t)
      case None => complete(ifEmptyStatus, None)
    }

  def completeWithLocationHeader[T](status: Int, resourceId: T): Route =
    extractRequestContext { requestContext =>
      val request = requestContext.request
      val location = request.uri.copy(path = request.uri.path / resourceId.toString)
      respondWithHeader(Location(location)) {
        complete(status, None)
      }
    }

  def complete[T: ToResponseMarshaller](resource: Future[Option[T]]): Route =
    onSuccess(resource) {
      case Some(t) => complete(ToResponseMarshallable(t))
      case None => complete(404, None)
    }

  def complete(resource: Future[Unit]): Route = onSuccess(resource) { complete(204, None) }

} 
Example 125
Source File: QuestionResource.scala    From quiz-management-service   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.quiz.management.resources

import akka.http.scaladsl.server.Route

import com.danielasfregola.quiz.management.entities.{Question, QuestionUpdate}
import com.danielasfregola.quiz.management.routing.MyResource
import com.danielasfregola.quiz.management.services.QuestionService

trait QuestionResource extends MyResource {

  val questionService: QuestionService

  def questionRoutes: Route = pathPrefix("questions") {
    pathEnd {
      post {
        entity(as[Question]) { question =>
          completeWithLocationHeader(
            resourceId = questionService.createQuestion(question),
            ifDefinedStatus = 201, ifEmptyStatus = 409)
          }
        }
    } ~
    path(Segment) { id =>
      get {
        complete(questionService.getQuestion(id))
      } ~
      put {
        entity(as[QuestionUpdate]) { update =>
          complete(questionService.updateQuestion(id, update))
        }
      } ~
      delete {
        complete(questionService.deleteQuestion(id))
      }
    }

  }
} 
Example 126
Source File: FrontPage.scala    From scaladex   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package ch.epfl.scala.index.server.routes

import ch.epfl.scala.index.model.misc.UserInfo
import ch.epfl.scala.index.server.TwirlSupport._
import ch.epfl.scala.index.views.html.frontpage
import com.softwaremill.session.SessionDirectives._
import com.softwaremill.session.SessionOptions._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.scala.index.server.GithubUserSession
import ch.epfl.scala.index.search.DataRepository

import scala.concurrent.ExecutionContext

class FrontPage(dataRepository: DataRepository,
                session: GithubUserSession)(implicit ec: ExecutionContext) {
  import session.implicits._

  private def frontPage(userInfo: Option[UserInfo]) = {
    import dataRepository._
    val topicsF = getAllTopics()
    val targetTypesF = getAllTargetTypes()
    val scalaVersionsF = getAllScalaVersions()
    val scalaJsVersionsF = getAllScalaJsVersions()
    val scalaNativeVersionsF = getAllScalaNativeVersions()
    val sbtVersionsF = getAllSbtVersions()
    val mostDependedUponF = getMostDependentUpon()
    val latestProjectsF = getLatestProjects()
    val latestReleasesF = getLatestReleases()
    val totalProjectsF = getTotalProjects()
    val totalReleasesF = getTotalReleases()
    val contributingProjectsF = getContributingProjects()

    for {
      topics <- topicsF
      targetTypes <- targetTypesF
      scalaVersions <- scalaVersionsF
      scalaJsVersions <- scalaJsVersionsF
      scalaNativeVersions <- scalaNativeVersionsF
      sbtVersions <- sbtVersionsF
      mostDependedUpon <- mostDependedUponF
      latestProjects <- latestProjectsF
      latestReleases <- latestReleasesF
      totalProjects <- totalProjectsF
      totalReleases <- totalReleasesF
      contributingProjects <- contributingProjectsF
    } yield {

      def query(label: String)(xs: String*): String =
        xs.map(v => s"$label:$v").mkString("search?q=", " OR ", "")

      val ecosystems = Map(
        "Akka" -> query("topics")("akka",
                                  "akka-http",
                                  "akka-persistence",
                                  "akka-streams"),
        "Scala.js" -> "search?targets=scala.js_0.6",
        "Spark" -> query("depends-on")("apache/spark-streaming",
                                       "apache/spark-graphx",
                                       "apache/spark-hive",
                                       "apache/spark-mllib",
                                       "apache/spark-sql"),
        "Typelevel" -> "typelevel"
      )

      frontpage(
        topics,
        targetTypes,
        scalaVersions,
        scalaJsVersions,
        scalaNativeVersions,
        sbtVersions,
        latestProjects,
        mostDependedUpon,
        latestReleases,
        userInfo,
        ecosystems,
        totalProjects,
        totalReleases,
        contributingProjects
      )
    }
  }

  val routes: Route =
    pathSingleSlash {
      optionalSession(refreshable, usingCookies) { userId =>
        complete(frontPage(session.getUser(userId).map(_.info)))
      }
    }
} 
Example 127
Source File: HTTPServer.scala    From ForestFlow   with Apache License 2.0 5 votes vote down vote up
package ai.forestflow.serving.restapi

import ai.forestflow.serving.config.ApplicationEnvironment
import akka.Done
import akka.actor.CoordinatedShutdown.{PhaseServiceUnbind, Reason}
import akka.actor.SupervisorStrategy._
import akka.actor.{ActorRef, ActorSystem, CoordinatedShutdown}
import akka.cluster.Cluster
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.util.Timeout
import ai.forestflow.akka.Supervisor
import ai.forestflow.domain.ServableRoutes.GetProxyRoutes
import ai.forestflow.utils.ThrowableImplicits._

import scala.concurrent.Await
import scala.concurrent.duration._
import scala.language.postfixOps
import scala.util.{Failure, Success}

//noinspection TypeAnnotation
object HTTPServer {

  private final case object BindFailure extends Reason

}
//noinspection TypeAnnotation
class HTTPServer(servableProxyRef: ActorRef)(implicit system: ActorSystem, cluster: Cluster, shutdown: CoordinatedShutdown) {
  import HTTPServer._
  import system.log

  private implicit val materializer = ActorMaterializer()
  private implicit val executionContext = system.dispatcher
  implicit lazy val timeout: Timeout = Timeout(ApplicationEnvironment.HTTP_COMMAND_TIMEOUT_SECS seconds)

  private val address = ApplicationEnvironment.HTTP_BIND_ADDRESS
  private val port = ApplicationEnvironment.HTTP_PORT

  val routesSupervisor = system.actorOf(Supervisor.props {
    case _: ArithmeticException => Resume
    case _: Exception => Restart
  })


  private val servableRoutesActor = Await.result(
    routesSupervisor
      .ask(ServableRoutes.props(servableProxyRef))
      .mapTo[ActorRef], ApplicationEnvironment.HTTP_COMMAND_TIMEOUT_SECS second)

  servableRoutesActor.ask(GetProxyRoutes()).onComplete {
    case Success(r: Route) =>
      val bindingFuture = Http().bindAndHandle(r, address, port)
      bindingFuture.onComplete {
        case Success(bound) =>
          log.info(s"AKKA HTTP Server online at http://${bound.localAddress.getHostString}:${bound.localAddress.getPort}/")
          shutdown.addTask(PhaseServiceUnbind, "api.unbind") { () =>
            bound.terminate(5 seconds).map(_ => Done)
          }
        case Failure(e) =>
          log.error(s"AKKA HTTP Server could not start! Shutting down... ${e.printableStackTrace}")
          shutdown.run(BindFailure)
      }

    case Failure(e) =>
      log.error(s"Couldn't get dynamic HTTP routes from ServableRoutes actor! Shutting down... ${e.printableStackTrace}")
      shutdown.run(BindFailure)
  }


} 
Example 128
Source File: AkkaHttpLambdaHandler.scala    From scala-server-lambda   with MIT License 5 votes vote down vote up
package io.github.howardjohn.lambda.akka

import akka.actor.ActorSystem
import akka.http.scaladsl.model.HttpHeader.ParsingResult
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}
import io.github.howardjohn.lambda.ProxyEncoding._
import io.github.howardjohn.lambda.{LambdaHandler, ProxyEncoding}

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}

class AkkaHttpLambdaHandler(route: Route)(
  implicit system: ActorSystem,
  materializer: ActorMaterializer,
  ec: ExecutionContext
) extends LambdaHandler {
  import AkkaHttpLambdaHandler._

  override def handleRequest(request: ProxyRequest): ProxyResponse =
    Await.result(runRequest(proxyToAkkaRequest(request)), Duration.Inf)

  private def runRequest(request: HttpRequest): Future[ProxyResponse] = {
    val source = Source.single(request)
    val sink = Sink.head[HttpResponse]
    source
      .via(route)
      .toMat(sink)(Keep.right)
      .run()
      .flatMap(asProxyResponse)
  }

  private def proxyToAkkaRequest(request: ProxyRequest): HttpRequest =
    new HttpRequest(
      method = parseHttpMethod(request.httpMethod),
      uri = Uri(ProxyEncoding.reconstructPath(request)),
      headers = parseRequestHeaders(request.headers.getOrElse(Map.empty)),
      entity = parseEntity(request.headers.getOrElse(Map.empty), request.body),
      protocol = HttpProtocols.`HTTP/1.1`
    )

  private def parseEntity(headers: Map[String, String], body: Option[String]): MessageEntity = {
    val defaultContentType = ContentTypes.`text/plain(UTF-8)`
    val contentType = ContentType
      .parse(headers.getOrElse("Content-Type", defaultContentType.value))
      .getOrElse(defaultContentType)

    body match {
      case Some(b) => HttpEntity(contentType, b.getBytes)
      case None => HttpEntity.empty(contentType)
    }
  }

  private def asProxyResponse(resp: HttpResponse): Future[ProxyResponse] =
    Unmarshal(resp.entity)
      .to[String]
      .map { body =>
        ProxyResponse(
          resp.status.intValue(),
          resp.headers.map(h => h.name -> h.value).toMap,
          body
        )
      }
}

private object AkkaHttpLambdaHandler {
  private def parseRequestHeaders(headers: Map[String, String]): List[HttpHeader] =
    headers.map {
      case (k, v) =>
        HttpHeader.parse(k, v) match {
          case ParsingResult.Ok(header, _) => header
          case ParsingResult.Error(err) => throw new RuntimeException(s"Failed to parse header $k:$v with error $err.")
        }
    }.toList

  private def parseHttpMethod(method: String) = method.toUpperCase match {
    case "CONNECT" => HttpMethods.CONNECT
    case "DELETE" => HttpMethods.DELETE
    case "GET" => HttpMethods.GET
    case "HEAD" => HttpMethods.HEAD
    case "OPTIONS" => HttpMethods.OPTIONS
    case "PATCH" => HttpMethods.PATCH
    case "POST" => HttpMethods.POST
    case "PUT" => HttpMethods.PUT
    case "TRACE" => HttpMethods.TRACE
    case other => HttpMethod.custom(other)
  }
} 
Example 129
Source File: AkkaHttpLambdaHandlerSpec.scala    From scala-server-lambda   with MIT License 5 votes vote down vote up
package io.github.howardjohn.lambda.akka

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{HttpEntity, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import akka.stream.ActorMaterializer
import io.circe.parser.decode
import io.circe.syntax._
import io.circe.{Decoder, Encoder}
import io.github.howardjohn.lambda.LambdaHandlerBehavior
import io.github.howardjohn.lambda.LambdaHandlerBehavior._
import org.scalatest.{BeforeAndAfterAll, FeatureSpec, GivenWhenThen}

import scala.concurrent.Future

class AkkaHttpLambdaHandlerSpec
    extends FeatureSpec
    with LambdaHandlerBehavior
    with GivenWhenThen
    with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem("test")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = scala.concurrent.ExecutionContext.Implicits.global

  val route: Route =
    path("hello") {
      (get & parameter("times".as[Int] ? 1)) { times =>
        complete {
          Seq
            .fill(times)("Hello World!")
            .mkString(" ")
        }
      }
    } ~ path("long") {
      get {
        Thread.sleep(1000)
        complete("")
      }
    } ~ path("post") {
      post {
        entity(as[String]) { body =>
          complete(body)
        }
      }
    } ~ path("json") {
      post {
        import CirceJsonMarshalling._
        import io.circe.generic.auto._
        entity(as[JsonBody]) { entity =>
          complete(LambdaHandlerBehavior.jsonReturn.asJson)
        }
      }
    } ~ path("exception") {
      get {
        throw RouteException()
      }
    } ~ path("error") {
      get {
        complete(StatusCodes.InternalServerError)
      }
    } ~ path("header") {
      get {
        headerValueByName(inputHeader) { header =>
          respondWithHeaders(RawHeader(outputHeader, outputHeaderValue)) {
            complete(header)
          }
        }
      }
    }

  val handler = new AkkaHttpLambdaHandler(route)

  scenariosFor(behavior(handler))

  override def afterAll(): Unit = {
    materializer.shutdown()
    system.terminate()
  }
}


object CirceJsonMarshalling {
  implicit final def unmarshaller[A: Decoder]: FromEntityUnmarshaller[A] =
    Unmarshaller.stringUnmarshaller
      .forContentTypes(`application/json`)
      .flatMap { ctx => mat => json =>
        decode[A](json).fold(Future.failed, Future.successful)
      }

  implicit final def marshaller[A: Encoder]: ToEntityMarshaller[A] =
    Marshaller.withFixedContentType(`application/json`) { a =>
      HttpEntity(`application/json`, a.asJson.noSpaces)
    }
} 
Example 130
Source File: Route.scala    From scala-server-lambda   with MIT License 5 votes vote down vote up
package io.github.howardjohn.lambda.akka.example

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import io.github.howardjohn.lambda.akka.AkkaHttpLambdaHandler

object Route {
  // Set up the route
  val route: Route =
    path("hello" / Segment) { name: String =>
      get {
        complete(s"Hello, $name!")
      }
    }

  // Set up dependencies
  implicit val system: ActorSystem = ActorSystem("example")
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec = scala.concurrent.ExecutionContext.Implicits.global

  // Define the entry point for Lambda
  class EntryPoint extends AkkaHttpLambdaHandler(route)
} 
Example 131
Source File: ServerExecutor.scala    From graphcool-framework   with Apache License 2.0 5 votes vote down vote up
package cool.graph.akkautil.http

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import ch.megard.akka.http.cors.scaladsl.CorsDirectives
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._

import scala.concurrent.duration.{Duration, _}
import scala.concurrent.{Await, Future}


case class ServerExecutor(port: Int, servers: Server*)(implicit system: ActorSystem, materializer: ActorMaterializer) {
  import system.dispatcher

  val routes: Route = {
    handleRejections(CorsDirectives.corsRejectionHandler) {
      cors() {
        val routes = servers.map(_.routes) :+ statusRoute
        routes.reduceLeft(_ ~ _)
      }
    }
  }

  def statusRoute: Route = (get & path("status")) {
    val checks = Future.sequence(servers.map(_.healthCheck))

    onSuccess(checks) { _ =>
      complete("OK")
    }
  }

  lazy val serverBinding: Future[ServerBinding] = {
    val binding = Http().bindAndHandle(Route.handlerFlow(routes), "0.0.0.0", port)
    binding.onSuccess { case b => println(s"Server running on :${b.localAddress.getPort}") }
    binding
  }

  def start: Future[_] = Future.sequence[Any, Seq](servers.map(_.onStart) :+ serverBinding)
  def stop: Future[_]  = Future.sequence[Any, Seq](servers.map(_.onStop) :+ serverBinding.map(_.unbind))

  // Starts the server and blocks the calling thread until the underlying actor system terminates.
  def startBlocking(duration: Duration = 15.seconds): Unit = {
    start
    Await.result(system.whenTerminated, Duration.Inf)
  }

  def stopBlocking(duration: Duration = 15.seconds): Unit = Await.result(stop, duration)
} 
Example 132
Source File: Server.scala    From graphcool-framework   with Apache License 2.0 5 votes vote down vote up
package cool.graph.akkautil.http

import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.Directives.pathPrefix
import scala.concurrent.Future

trait Server {
  val prefix: String

  protected val innerRoutes: Route

  def routes: Route = prefix match {
    case prfx if prfx.nonEmpty => pathPrefix(prfx) { innerRoutes }
    case _                     => innerRoutes
  }

  def onStart: Future[_] = Future.successful(())
  def onStop: Future[_]  = Future.successful(())

  final def healthCheck: Future[_] = Future.successful(())
} 
Example 133
Source File: Endpoints.scala    From akka-http-microservice-templates   with MIT License 5 votes vote down vote up
package io.github.gabfssilva.endpoints

import java.lang.System.currentTimeMillis

import akka.actor.ActorSystem
import akka.event.{Logging, LoggingAdapter}
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.RouteResult.Complete
import akka.http.scaladsl.server.directives.{DebuggingDirectives, LogEntry, LoggingMagnet}
import akka.http.scaladsl.settings.RoutingSettings
import akka.stream.{ActorMaterializer, Materializer}

import scala.concurrent.ExecutionContext

class Endpoints(greetingEndpoint: GreetingEndpoint,
                healthCheckEndpoint: HealthCheckEndpoint) {
  def routes(implicit
             sys: ActorSystem,
             mat: ActorMaterializer,
             ec: ExecutionContext) = loggableRoute {
    Route.seal {
      greetingEndpoint.greetingRoute ~ healthCheckEndpoint.healthCheckRoute
    }
  }

  def logRequestAndResponse(loggingAdapter: LoggingAdapter, before: Long)(req: HttpRequest)(res: Any): Unit = {
    val entry = res match {
      case Complete(resp) =>
        val message = s"{path=${req.uri}, method=${req.method.value}, status=${resp.status.intValue()}, elapsedTime=${currentTimeMillis() - before}"
        LogEntry(message, Logging.InfoLevel)
      case other => LogEntry(other, Logging.InfoLevel)
    }

    entry.logTo(loggingAdapter)
  }

  def loggableRoute(route: Route)(implicit m: Materializer,
                                  ex: ExecutionContext,
                                  routingSettings: RoutingSettings): Route = {
    DebuggingDirectives.logRequestResult(LoggingMagnet(log => {
      val requestTimestamp = currentTimeMillis()
      logRequestAndResponse(log, requestTimestamp)
    }))(route)
  }
} 
Example 134
Source File: AkkaHttpCustomHeadersTest.scala    From guardrail   with MIT License 5 votes vote down vote up
package generators.AkkaHttp.RoundTrip

import akka.actor.ActorSystem
import akka.http.scaladsl.server.{ Route }
import akka.stream.ActorMaterializer
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.SpanSugar._
import org.scalatest.{ EitherValues, FlatSpec, Matchers }
import scala.concurrent.ExecutionContext.Implicits.global
import tests.customTypes.customHeader.client.akkaHttp.Client
import tests.customTypes.customHeader.client.akkaHttp.{ definitions => cdefs }
import tests.customTypes.customHeader.server.akkaHttp.Implicits.Formatter
import tests.customTypes.customHeader.server.akkaHttp.{ definitions => sdefs, Handler, Resource }
import scala.concurrent.Future

class AkkaHttpCustomHeadersTest extends FlatSpec with Matchers with ScalaFutures with EitherValues {

  override implicit val patienceConfig = PatienceConfig(10 seconds, 1 second)

  it should "encode custom headers" in {
    Formatter.show(sdefs.Bar.V1) shouldBe "v1"
    Formatter.show(sdefs.Bar.ILikeSpaces) shouldBe "i like spaces"
  }

  it should "round-trip encoded values" in {
    implicit val as  = ActorSystem()
    implicit val mat = ActorMaterializer()
    val client = Client.httpClient(Route.asyncHandler(Resource.routes(new Handler {
      def getFoo(respond: Resource.GetFooResponse.type)(
          header: String,
          longHeader: Long,
          customHeader: sdefs.Bar,
          customOptionHeader: Option[sdefs.Bar],
          missingCustomOptionHeader: Option[sdefs.Bar]
      ): Future[Resource.GetFooResponse] =
        (header, longHeader, customHeader, customOptionHeader, missingCustomOptionHeader) match {
          case ("foo", 5L, sdefs.Bar.V1, Some(sdefs.Bar.V2), None) => Future.successful(respond.OK)
          case _                                                   => Future.successful(respond.BadRequest)
        }
    })))

    client.getFoo("foo", 5L, cdefs.Bar.V1, Some(cdefs.Bar.V2), None).value.futureValue.right.value
  }

} 
Example 135
Source File: PermissionsRoutes.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator
import ch.epfl.bluebrain.nexus.iam.marshallers.instances._
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], realms: Realms[Task])(implicit http: HttpConfig) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _ => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev =>
                complete(permissions.delete(rev).runToFuture)
              }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set) =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _ =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  private[routes] sealed trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe = hc.get[String]("@type").getOrElse("Replace")
          patch <- tpe match {
            case "Replace"  => Right(Replace(permissions))
            case "Append"   => Right(Append(permissions))
            case "Subtract" => Right(Subtract(permissions))
            case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
          }
        } yield patch
      }
  }

} 
Example 136
Source File: IdentitiesRoutes.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator
import ch.epfl.bluebrain.nexus.iam.marshallers.instances._
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.types.Caller
import ch.epfl.bluebrain.nexus.iam.types.Caller.JsonLd._
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class IdentitiesRoutes(realms: Realms[Task])(implicit http: HttpConfig) {

  def routes: Route = {
    (pathPrefix("identities") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/identities") {
        authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller =>
          get {
            complete(caller)
          }
        }
      }
    }
  }
} 
Example 137
Source File: RealmDirectivesSpec.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.directives

import java.net.URLEncoder

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.http.JsonLdCirceSupport._
import ch.epfl.bluebrain.nexus.commons.test.EitherValues
import ch.epfl.bluebrain.nexus.iam.directives.RealmDirectives._
import ch.epfl.bluebrain.nexus.iam.routes.SearchParams
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.generic.auto._
import org.mockito.IdiomaticMockito
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class RealmDirectivesSpec
    extends AnyWordSpecLike
    with ScalatestRouteTest
    with Matchers
    with ScalaFutures
    with EitherValues
    with IdiomaticMockito {

  private def route: Route = {
    (get & searchParams) { params =>
      complete(params)

    }
  }

  private def encode(s: AbsoluteIri) = URLEncoder.encode(s.asString, "UTF-8")

  "Realm directives" should {
    "return query params" in {
      val createdBy: AbsoluteIri = url"http://example.com/created"
      val updatedBy: AbsoluteIri = url"http://example.com/updated"
      val tpe: AbsoluteIri       = url"http://example.com/tpe"
      val tpe2: AbsoluteIri      = url"http://example.com/tpe2"
      Get(
        s"/?rev=2&deprecated=true&type=${encode(tpe)}&type=${encode(tpe2)}&createdBy=${encode(createdBy)}&updatedBy=${encode(updatedBy)}"
      ) ~> route ~> check {
        responseAs[SearchParams] shouldEqual SearchParams(
          Some(true),
          Some(2L),
          Some(createdBy),
          Some(updatedBy),
          Set(tpe, tpe2)
        )
      }
    }
  }

} 
Example 138
Source File: HttpApi.scala    From jwt-akka-http   with MIT License 5 votes vote down vote up
package ba.codecentric

import java.util.concurrent.TimeUnit

import akka.actor.{ Actor, ActorLogging, Props }
import akka.http.scaladsl.Http
import akka.http.scaladsl.Http.ServerBinding
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server.{ Directive1, Route }
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer
import akka.pattern._

import scala.util.Failure

object HttpApi {
  import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
  import io.circe.generic.auto._
  import authentikat.jwt._

  final val Name                  = "http-api"
  final val AccessTokenHeaderName = "X-Access-Token"

  final case class LoginRequest(username: String, password: String)

  private val tokenExpiryPeriodInDays = 1
  private val secretKey               = "super_secret_key"
  private val header                  = JwtHeader("HS256")

  private def login: Route = post {
    entity(as[LoginRequest]) {
      case lr @ LoginRequest("admin", "admin") =>
        val claims = setClaims(lr.username, tokenExpiryPeriodInDays)
        respondWithHeader(RawHeader(AccessTokenHeaderName, JsonWebToken(header, claims, secretKey))) {
          complete(StatusCodes.OK)
        }
      case LoginRequest(_, _) => complete(StatusCodes.Unauthorized)
    }
  }

  private def securedContent: Route = get {
    authenticated { claims =>
      complete(s"User: ${claims.getOrElse("user", "")} has accessed a secured content!")
    }
  }

  private def authenticated: Directive1[Map[String, Any]] =
    optionalHeaderValueByName("Authorization").flatMap {
      case Some(jwt) if isTokenExpired(jwt) =>
        complete(StatusCodes.Unauthorized -> "Session expired.")

      case Some(jwt) if JsonWebToken.validate(jwt, secretKey) =>
        provide(getClaims(jwt))

      case _ => complete(StatusCodes.Unauthorized)
    }

  private def setClaims(username: String, expiryPeriodInDays: Long): JwtClaimsSetMap =
    JwtClaimsSet(
      Map("user" -> username,
          "expiredAt" -> (System.currentTimeMillis() + TimeUnit.DAYS
            .toMillis(expiryPeriodInDays)))
    )

  private def getClaims(jwt: String): Map[String, String] = jwt match {
    case JsonWebToken(_, claims, _) => claims.asSimpleMap.getOrElse(Map.empty[String, String])
  }

  private def isTokenExpired(jwt: String): Boolean =
    getClaims(jwt).get("expiredAt").exists(_.toLong < System.currentTimeMillis())

  def routes: Route = login ~ securedContent

  def apply(host: String, port: Int) = Props(new HttpApi(host, port))
}

final class HttpApi(host: String, port: Int) extends Actor with ActorLogging {
  import HttpApi._
  import context.dispatcher

  private implicit val materializer: ActorMaterializer = ActorMaterializer()

  Http(context.system).bindAndHandle(routes, host, port).pipeTo(self)

  override def receive: Receive = {
    case ServerBinding(address) =>
      log.info("Server successfully bound at {}:{}", address.getHostName, address.getPort)
    case Failure(cause) =>
      log.error("Failed to bind server", cause)
      context.system.terminate()
  }
} 
Example 139
Source File: HealthCheckRouting.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.{Directives, Route}
import akka.util.Timeout
import vinyldns.core.health.HealthService

import scala.concurrent.duration._

trait PingRoute extends Directives {

  val pingRoute: Route = (get & path("ping")) {
    complete("PONG")
  }
}

trait HealthCheckRoute extends Directives {

  val healthService: HealthService

  implicit val healthCheckTimeout = Timeout(5.seconds)

  // perform a query against, fail with an ok if we can get zones from the zone manager
  val healthCheckRoute =
    (get & path("health")) {
      onSuccess(healthService.checkHealth().unsafeToFuture()) {
        case head :: _ => failWith(head)
        case _ => complete(StatusCodes.OK)
      }
    }

} 
Example 140
Source File: ReplSupport.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.server

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ammonite.repl.Bind

trait ReplSupport extends WebSocketRepl {

  def replRouting: Route = {
    path("repl") {
      replWebSocketRoute
    }
  }

  protected override def replArgs: Seq[Bind[_]] = Nil

  protected override def replPredef: String =
    """
      |import Predef.{println => _}
      |import pprint.{pprintln => println}
      |import akkaviz.events.ActorSystems.systems
      |import scala.concurrent.duration._
      |import akka.actor._
      |import akka.pattern._
    """.stripMargin

} 
Example 141
Source File: ArchiveSupport.scala    From akka-viz   with MIT License 5 votes vote down vote up
package akkaviz.server

import akka.http.scaladsl.marshalling.Marshaller
import akka.http.scaladsl.marshalling.Marshalling.WithFixedContentType
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.scaladsl.{Flow, Source}
import akkaviz.config.Config
import akkaviz.persistence.{PersistenceSources, ReceivedRecord}
import akkaviz.rest
import com.datastax.driver.core.utils.UUIDs
import org.reactivestreams.Publisher

import scala.concurrent.ExecutionContext.Implicits.global

trait ArchiveSupport {

  def isArchiveEnabled: Boolean

  def receivedOf(ref: String): Source[ReceivedRecord, _]

  def receivedBetween(ref: String, ref2: String): Source[ReceivedRecord, _]

  def archiveRouting: Route = get {
    pathPrefix("messages") {
      if (isArchiveEnabled) {
        path("of" / Segment) {
          ref =>
            AkkaHttpHelpers.completeAsJson(receivedOf(ref).via(receivedRecordToRestReceived))
        } ~
          path("between" / Segment / Segment) {
            (ref, ref2) =>
              AkkaHttpHelpers.completeAsJson(receivedBetween(ref, ref2).via(receivedRecordToRestReceived))
          }
      } else {
        reject
      }
    }
  }

  private[this] implicit val receivedRecordMarshaller: Marshaller[rest.Received, String] = Marshaller.strict {
    received =>
      WithFixedContentType(MediaTypes.`application/json`, () => upickle.default.write(received))
  }

  private[this] def receivedRecordToRestReceived = Flow[ReceivedRecord].map {
    rr =>
      rest.Received(rr.millis, rr.direction, rr.first, rr.second, rr.data)
  }

} 
Example 142
Source File: PermissionControllers.scala    From akka-http-extensions   with Mozilla Public License 2.0 5 votes vote down vote up
package akka.http.extensions


import akka.http.extensions.security._
import akka.http.scaladsl.server.{Directives, Route}

import scala.collection.mutable


case object SpecialRealm extends Realm
case object VIPRealm extends Realm

trait PermissionControllers extends RegistrationControllers
{
  class Permissions(sessionController: TestSessionController,loginController: TestLoginController) extends AuthDirectives with Directives
  {
    case object OtherRealm extends Realm

    var drugs:Set[String] = Set.empty

    val permissions = new mutable.HashMap[Realm, mutable.Set[LoginInfo]] with mutable.MultiMap[Realm, LoginInfo]

    def checkRights(user:LoginInfo,realm:Realm):Boolean = if(realm==UserRealm)
        loginController.exists(user)
      else
        permissions.get(realm).exists(_.contains(user))

    def add2realm(user:LoginInfo,realm: Realm) ={
      permissions.addBinding(realm,user)
    }

    def removeFromRealm(user:LoginInfo,realm: Realm) ={
      permissions.removeBinding(realm,user)
    }

    lazy val realms: Map[String, Realm] = Map("user"->UserRealm,"vip"->VIPRealm,"special"->SpecialRealm,""->UserRealm)


    def routes: Route =
      pathPrefix("add") {
        pathPrefix("drug") {
          put
          {
            parameter("name","kind"){ (name,kind)=>
              authenticate(sessionController.userByToken _){ user=>
                val realm: Realm = realms.getOrElse(kind, realms("user"))
                allow(user,realm, checkRights _)
                {
                  drugs = drugs + name
                  complete(s"drug $name added!")
                }
              }

            }
          }
        }
      }
  }
} 
Example 143
Source File: WSApi.scala    From mist   with Apache License 2.0 5 votes vote down vote up
package io.hydrosphere.mist.master.interfaces.http

import akka.http.scaladsl.model.ws._
import akka.http.scaladsl.server.{Directives, Route}
import akka.stream.ActorAttributes.supervisionStrategy
import akka.stream.Supervision.resumingDecider
import akka.stream.{ActorAttributes, Supervision}
import akka.stream.scaladsl.{Flow, Sink}
import io.hydrosphere.mist.master.EventsStreamer
import io.hydrosphere.mist.master.Messages.StatusMessages._
import io.hydrosphere.mist.master.interfaces.JsonCodecs

import scala.concurrent.duration._
import spray.json._

import scala.language.postfixOps


class WSApi(streamer: EventsStreamer)(implicit val keepAliveTimeout: FiniteDuration) {

  import Directives._
  import JsonCodecs._

  val route: Route = {
    pathPrefix("v2" / "api"/ "ws" ) { parameter('withLogs ? false)  { withLogs =>
      path("all") {
        get {
          handleWebSocketMessagesWithKeepAlive(allEventsWsFlow(withLogs))
        }
      } ~
      path("jobs" / Segment) { jobId =>
        get {
          handleWebSocketMessagesWithKeepAlive(jobWsFlow(jobId, withLogs))
        }
      }
    }}
  }

  private def handleWebSocketMessagesWithKeepAlive(handler: Flow[Message, Message, akka.NotUsed]): Route =
    handleWebSocketMessages(handler
      .withAttributes(supervisionStrategy(resumingDecider))
      .keepAlive(
        keepAliveTimeout,
        () => TextMessage.Strict(KeepAliveEvent.asInstanceOf[SystemEvent].toJson.toString())
      ))


  private def jobWsFlow(id: String, withLogs: Boolean): Flow[Message, Message, akka.NotUsed] = {
    val source = streamer.eventsSource()
      .filter({
        case e: UpdateStatusEvent => e.id == id
        case e: ReceivedLogs if withLogs => e.id == id
        case _ => false
      })
      .map(toWsMessage)

    val sink = Sink.ignore
    Flow.fromSinkAndSource(sink, source)
  }

  private def allEventsWsFlow(withLogs: Boolean): Flow[Message, Message, akka.NotUsed] = {
    val source = streamer.eventsSource()
      .filter({
        case _: ReceivedLogs => withLogs
        case _ => true
      })
      .map(toWsMessage)

    val sink = Sink.ignore
    Flow.fromSinkAndSource(sink, source)
  }

  private def toWsMessage(e: SystemEvent): Message = TextMessage.Strict(e.toJson.toString())
} 
Example 144
Source File: HttpUi.scala    From mist   with Apache License 2.0 5 votes vote down vote up
package io.hydrosphere.mist.master.interfaces.http

import akka.http.scaladsl.model._
import akka.http.scaladsl.server.directives.ContentTypeResolver.Default
import akka.http.scaladsl.server.{Directives, RejectionHandler, Route}


  private val fallbackToSpa = RejectionHandler.newBuilder()
    .handleNotFound(getFromFile(index))
    .result()

  val route: Route = {
    pathPrefix("ui") {
      get {
        pathEnd {
          redirect("/ui/", PermanentRedirect)
        } ~
        pathSingleSlash {
          getFromFile(index)
        } ~
        handleRejections(fallbackToSpa) {
          getFromDirectory(path)
        }
      }
    }
  }

} 
Example 145
Source File: GrpcInteropSpec.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package akka.grpc.interop

import akka.stream.{ Materializer, SystemMaterializer }
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.RouteResult.Complete
import akka.http.scaladsl.server.{ Directive0, Directives, Route }
import io.grpc.testing.integration.TestServiceHandlerFactory
import io.grpc.testing.integration.test.TestService
import org.scalatest.WordSpec

import scala.collection.immutable

// Generated by our plugin
import io.grpc.testing.integration.test.TestServiceHandler

class GrpcInteropIoWithAkkaSpec extends GrpcInteropTests(IoGrpcJavaServerProvider, AkkaHttpClientProviderScala)

class GrpcInteropAkkaScalaWithIoSpec extends GrpcInteropTests(AkkaHttpServerProviderScala, IoGrpcJavaClientProvider)
class GrpcInteropAkkaScalaWithAkkaSpec extends GrpcInteropTests(AkkaHttpServerProviderScala, AkkaHttpClientProviderScala)

class GrpcInteropAkkaJavaWithIoSpec extends GrpcInteropTests(AkkaHttpServerProviderJava, IoGrpcJavaClientProvider)
class GrpcInteropAkkaJavaWithAkkaSpec extends GrpcInteropTests(AkkaHttpServerProviderJava, AkkaHttpClientProviderScala)

object AkkaHttpServerProviderScala extends AkkaHttpServerProvider {
  import Directives._

  val label: String = "akka-grpc server scala"
  val pendingCases = Set()

  val server = AkkaGrpcServerScala(implicit sys => {
    implicit val ec = sys.dispatcher

    val requestHandler = TestServiceHandler(new TestServiceImpl())

    val route: Route = (pathPrefix(TestService.name) & echoHeaders) { ctx =>
      requestHandler(ctx.request).map(Complete)
    }

    implicit val mat: Materializer = SystemMaterializer(sys).materializer
    Route.asyncHandler(Route.seal(route))
  })

  val echoHeaders: Directive0 = extractRequest.flatMap(request => {
    val initialHeaderToEcho = request.headers.find(_.name() == "x-grpc-test-echo-initial")
    val trailingHeaderToEcho = request.headers.find(_.name() == "x-grpc-test-echo-trailing-bin")

    mapResponseHeaders(h => h ++ initialHeaderToEcho) & mapTrailingResponseHeaders(h => h ++ trailingHeaderToEcho)
  })

  // TODO to be moved to the runtime lib (or even akka-http itself?)
  def mapTrailingResponseHeaders(f: immutable.Seq[HttpHeader] => immutable.Seq[HttpHeader]) =
    mapResponse(response =>
      response.withEntity(response.entity match {
        case HttpEntity.Chunked(contentType, data) => {
          HttpEntity.Chunked(contentType, data.map {
            case chunk: HttpEntity.Chunk => chunk
            case last: HttpEntity.LastChunk => HttpEntity.LastChunk(last.extension, f(last.trailer))
          })
        }
        case _ =>
          throw new IllegalArgumentException("Trailing response headers are only supported on Chunked responses")
      }))
}

object AkkaHttpServerProviderJava extends AkkaHttpServerProvider {
  val label: String = "akka-grpc server java"

  val pendingCases =
    Set(
      "custom_metadata"
    )

  val server = new AkkaGrpcServerJava((mat, sys) => {
    TestServiceHandlerFactory.create(new JavaTestServiceImpl(mat), sys)
  })
}

object AkkaHttpClientProviderScala extends AkkaHttpClientProvider {
  val label: String = "akka-grpc scala client tester"

  def client = AkkaGrpcClientScala(settings => implicit sys => new AkkaGrpcClientTester(settings))
} 
Example 146
Source File: WebHandler.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package akka.grpc.scaladsl

import scala.collection.immutable
import scala.concurrent.Future
import akka.actor.ClassicActorSystemProvider
import akka.annotation.ApiMayChange
import akka.http.javadsl.{ model => jmodel }
import akka.http.scaladsl.model.{ HttpMethods, HttpRequest, HttpResponse }
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.MarshallingDirectives.handleWith
import ch.megard.akka.http.cors.scaladsl.CorsDirectives.cors
import ch.megard.akka.http.cors.scaladsl.model.HttpHeaderRange
import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings

@ApiMayChange
object WebHandler {

  
  def grpcWebHandler(handlers: PartialFunction[HttpRequest, Future[HttpResponse]]*)(
      implicit as: ClassicActorSystemProvider,
      corsSettings: CorsSettings = defaultCorsSettings): HttpRequest => Future[HttpResponse] = {
    implicit val system = as.classicSystem
    val servicesHandler = ServiceHandler.concat(handlers: _*)
    Route.asyncHandler(cors(corsSettings) {
      handleWith(servicesHandler)
    })
  }

} 
Example 147
Source File: NodeRoutes.scala    From akka-cluster-playground   with MIT License 5 votes vote down vote up
package com.elleflorio.cluster.playground.api

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.marshallers.sprayjson._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout

import scala.concurrent.ExecutionContext.Implicits.global
import com.elleflorio.cluster.playground.node.processor.ProcessorResponseJsonProtocol._
import com.elleflorio.cluster.playground.node.Node.{GetClusterMembers, GetFibonacci}
import com.elleflorio.cluster.playground.node.processor.ProcessorResponse

import scala.concurrent.Future
import scala.concurrent.duration._

trait NodeRoutes extends SprayJsonSupport {

  implicit def system: ActorSystem

  def node: ActorRef

  implicit lazy val timeout = Timeout(5.seconds)

  lazy val healthRoute: Route = pathPrefix("health") {
    concat(
      pathEnd {
        concat(
          get {
            complete(StatusCodes.OK)
          }
        )
      }
    )
  }

  lazy val statusRoutes: Route = pathPrefix("status") {
    concat(
      pathPrefix("members") {
        concat(
          pathEnd {
            concat(
              get {
                val membersFuture: Future[List[String]] = (node ? GetClusterMembers).mapTo[List[String]]
                onSuccess(membersFuture) { members =>
                  complete(StatusCodes.OK, members)
                }
              }
            )
          }
        )
      }
    )
  }

  lazy val processRoutes: Route = pathPrefix("process") {
    concat(
      pathPrefix("fibonacci") {
        concat(
          path(IntNumber) { n =>
            pathEnd {
              concat(
                get {
                  val processFuture: Future[ProcessorResponse] = (node ? GetFibonacci(n)).mapTo[ProcessorResponse]
                  onSuccess(processFuture) { response =>
                    complete(StatusCodes.OK, response)
                  }
                }
              )
            }
          }
        )
      }
    )
  }
} 
Example 148
Source File: HealthEndpoint.scala    From akka-http-health   with MIT License 5 votes vote down vote up
package io.github.lhotari.akka.http.health

import java.util.concurrent.atomic.AtomicBoolean

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

import scala.concurrent.{ExecutionContext, Future}

trait HealthEndpoint {

  protected lazy val checkers = createCheckers

  protected def createCheckers = {
    Seq(new LowDiskSpaceDetector(), new LowMemoryDetector())
  }

  private lazy val successResponse: HttpResponse = createSuccessResponse

  protected def decorateResponse(response: HttpResponse) = response

  protected def createSuccessResponse = {
    decorateResponse(HttpResponse(entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, "OK")))
  }

  private lazy val errorResponse: HttpResponse = createErrorResponse

  protected def createErrorResponse = {
    decorateResponse(HttpResponse(status = StatusCodes.ServiceUnavailable))
  }

  private val started = new AtomicBoolean(false)

  def createHealthRoute(endpoint: String = HealthEndpoint.DefaultEndpoint)(implicit executor: ExecutionContext): Route =
    get {
      path(endpoint) {
        completeHealthCheck
      }
    }

  def completeHealthCheck(implicit executor: ExecutionContext) = {
    complete {
      Future {
        if (isHealthy()) successResponse else errorResponse
      }
    }
  }

  def start(): Unit = {
    if (started.compareAndSet(false, true)) {
      checkers.foreach(_.start())
    }
  }

  def stop(): Unit = {
    if (started.compareAndSet(true, false)) {
      checkers.foreach(_.stop())
    }
  }

  def isHealthy() = {
    start()
    checkers.forall(_.isHealthy())
  }
}

object HealthEndpoint extends HealthEndpoint {
  lazy val defaultHealthChecker = new HealthEndpoint {}

  val DefaultEndpoint: String = "health"

  def createDefaultHealthRoute(endpoint: String = DefaultEndpoint)(implicit executor: ExecutionContext): Route = {
    defaultHealthChecker.createHealthRoute(endpoint)
  }
} 
Example 149
Source File: HealthEndpointSpec.scala    From akka-http-health   with MIT License 5 votes vote down vote up
package io.github.lhotari.akka.http.health

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.mockito.Mockito._
import org.scalatest.{FunSpec, Matchers}
import org.scalatestplus.mockito.MockitoSugar

class HealthEndpointSpec extends FunSpec with Matchers with ScalatestRouteTest with MockitoSugar with HealthEndpoint {
  val mockChecker1 = mock[HealthChecker]
  val mockChecker2 = mock[HealthChecker]

  override protected def createCheckers(): Seq[HealthChecker] = Seq(mockChecker1, mockChecker2)

  describe("health endpoint") {
    it("should complete successfully when all checks are ok") {
      checkers.foreach(checker => when(checker.isHealthy()).thenReturn(true))
      Get("/health") ~> Route.seal(createHealthRoute()) ~> check {
        status shouldEqual StatusCodes.OK
      }
    }

    it("should complete successfully when a different endpoint is specified") {
      checkers.foreach(checker => when(checker.isHealthy()).thenReturn(true))
      Get("/another-endpoint") ~> Route.seal(createHealthRoute("another-endpoint")) ~> check {
        status shouldEqual StatusCodes.OK
      }
    }

    it("should return error when the wrong endpoint is specified") {
      checkers.foreach(checker => when(checker.isHealthy()).thenReturn(true))
      Get("/health") ~> Route.seal(createHealthRoute("another-endpoint")) ~> check {
        status shouldEqual StatusCodes.NotFound
      }
    }

    it("should return error when a check fails") {
      when(mockChecker2.isHealthy()).thenReturn(false)
      Get("/health") ~> Route.seal(createHealthRoute()) ~> check {
        status shouldEqual StatusCodes.ServiceUnavailable
      }
    }

    it("should have started each checker exactly once") {
      checkers.foreach(checker => verify(checker).start())
    }
  }

} 
Example 150
Source File: QueryValidationApi.scala    From NSDb   with Apache License 2.0 5 votes vote down vote up
package io.radicalbit.nsdb.web.routes

import akka.actor.ActorRef
import akka.event.LoggingAdapter
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import akka.util.Timeout
import io.radicalbit.nsdb.common.statement.SelectSQLStatement
import io.radicalbit.nsdb.protocol.MessageProtocol.Commands.ValidateStatement
import io.radicalbit.nsdb.protocol.MessageProtocol.Events._
import io.radicalbit.nsdb.security.http.NSDBAuthProvider
import io.radicalbit.nsdb.security.model.Metric
import io.radicalbit.nsdb.sql.parser.SQLStatementParser
import io.radicalbit.nsdb.sql.parser.StatementParserResult._
import io.swagger.annotations._
import javax.ws.rs.Path
import org.json4s.Formats

import scala.annotation.meta.field
import scala.util.{Failure, Success}

@ApiModel(description = "Query Validation body")
case class QueryValidationBody(@(ApiModelProperty @field)(value = "database name ") db: String,
                               @(ApiModelProperty @field)(value = "namespace name ") namespace: String,
                               @(ApiModelProperty @field)(value = "metric name ") metric: String,
                               @(ApiModelProperty @field)(value = "sql query string") queryString: String)
    extends Metric

@Api(value = "/query/validate", produces = "application/json")
@Path("/query/validate")
trait QueryValidationApi {

  import io.radicalbit.nsdb.web.NSDbJson._

  def readCoordinator: ActorRef
  def authenticationProvider: NSDBAuthProvider

  implicit val timeout: Timeout
  implicit val formats: Formats

  @ApiOperation(value = "Perform query", nickname = "query", httpMethod = "POST", response = classOf[String])
  @ApiImplicitParams(
    Array(
      new ApiImplicitParam(name = "body",
                           value = "query definition",
                           required = true,
                           dataTypeClass = classOf[QueryValidationBody],
                           paramType = "body")
    ))
  @ApiResponses(
    Array(
      new ApiResponse(code = 200, message = "Query is valid"),
      new ApiResponse(code = 404, message = "Not found item reason"),
      new ApiResponse(code = 400, message = "statement is invalid")
    ))
  def queryValidationApi(implicit logger: LoggingAdapter): Route = {
    path("query" / "validate") {
      post {
        entity(as[QueryValidationBody]) { qb =>
          optionalHeaderValueByName(authenticationProvider.headerName) { header =>
            authenticationProvider.authorizeMetric(ent = qb, header = header, writePermission = false) {
              new SQLStatementParser().parse(qb.db, qb.namespace, qb.queryString) match {
                case SqlStatementParserSuccess(_, statement: SelectSQLStatement) =>
                  onComplete(readCoordinator ? ValidateStatement(statement)) {
                    case Success(SelectStatementValidated(_)) =>
                      complete(HttpResponse(OK))
                    case Success(SelectStatementValidationFailed(_, reason, MetricNotFound(_))) =>
                      complete(HttpResponse(NotFound, entity = reason))
                    case Success(SelectStatementValidationFailed(_, reason, _)) =>
                      complete(HttpResponse(BadRequest, entity = reason))
                    case Success(r) =>
                      logger.error("unknown response received {}", r)
                      complete(HttpResponse(InternalServerError, entity = "unknown response"))
                    case Failure(ex) =>
                      logger.error("", ex)
                      complete(HttpResponse(InternalServerError, entity = ex.getMessage))
                  }
                case SqlStatementParserSuccess(queryString, _) =>
                  complete(HttpResponse(BadRequest, entity = s"statement ${queryString} is not a select statement"))
                case SqlStatementParserFailure(queryString, _) =>
                  complete(HttpResponse(BadRequest, entity = s"statement ${queryString} is invalid"))
              }
            }
          }
        }
      }
    }
  }
} 
Example 151
Source File: DataApi.scala    From NSDb   with Apache License 2.0 5 votes vote down vote up
package io.radicalbit.nsdb.web.routes

import javax.ws.rs.Path
import akka.actor.ActorRef
import akka.pattern.ask
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.StatusCodes.{BadRequest, InternalServerError}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import io.radicalbit.nsdb.common.protocol.Bit
import io.radicalbit.nsdb.protocol.MessageProtocol.Commands.MapInput
import io.radicalbit.nsdb.protocol.MessageProtocol.Events.{InputMapped, RecordRejected}
import io.radicalbit.nsdb.security.http.NSDBAuthProvider
import io.radicalbit.nsdb.security.model.Metric
import io.swagger.annotations._
import org.json4s.Formats

import scala.annotation.meta.field
import scala.util.{Failure, Success}

@ApiModel(description = "Data insertion body")
case class InsertBody(@(ApiModelProperty @field)(value = "database name") db: String,
                      @(ApiModelProperty @field)(value = "namespace name") namespace: String,
                      @(ApiModelProperty @field)(value = "metric name") metric: String,
                      @(ApiModelProperty @field)(
                        value = "bit representing a single row"
                      ) bit: Bit)
    extends Metric

@Api(value = "/data", produces = "application/json")
@Path("/data")
trait DataApi {

  import io.radicalbit.nsdb.web.NSDbJson._
  import io.radicalbit.nsdb.web.validation.ValidationDirective._
  import io.radicalbit.nsdb.web.validation.Validators._

  def writeCoordinator: ActorRef
  def authenticationProvider: NSDBAuthProvider

  implicit val timeout: Timeout
  implicit val formats: Formats

  @ApiOperation(value = "Insert Bit", nickname = "insert", httpMethod = "POST", response = classOf[String])
  @ApiImplicitParams(
    Array(
      new ApiImplicitParam(name = "body",
                           value = "bit definition",
                           required = true,
                           dataTypeClass = classOf[InsertBody],
                           paramType = "body")
    ))
  @ApiResponses(
    Array(
      new ApiResponse(code = 500, message = "Internal server error"),
      new ApiResponse(code = 400, message = "insert statement is invalid")
    ))
  def dataApi: Route =
    pathPrefix("data") {
      post {
        entity(as[InsertBody]) { insertBody =>
          optionalHeaderValueByName(authenticationProvider.headerName) { header =>
            validateModel(insertBody).apply { validatedInsertBody =>
              authenticationProvider.authorizeMetric(ent = validatedInsertBody, header = header, writePermission = true) {
                onComplete(
                  writeCoordinator ? MapInput(validatedInsertBody.bit.timestamp,
                                              validatedInsertBody.db,
                                              validatedInsertBody.namespace,
                                              validatedInsertBody.metric,
                                              validatedInsertBody.bit)) {
                  case Success(_: InputMapped) =>
                    complete("OK")
                  case Success(RecordRejected(_, _, _, _, _, reasons, _)) =>
                    complete(HttpResponse(BadRequest, entity = reasons.mkString(",")))
                  case Success(_) =>
                    complete(HttpResponse(InternalServerError, entity = "unknown response"))
                  case Failure(ex) => complete(HttpResponse(InternalServerError, entity = ex.getMessage))
                }
              }
            }
          }
        }
      }
    }

} 
Example 152
Source File: WebResources.scala    From NSDb   with Apache License 2.0 5 votes vote down vote up
package io.radicalbit.nsdb.web

import java.util.concurrent.TimeUnit

import akka.actor.ActorRef
import akka.event.LoggingAdapter
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import akka.util.Timeout
import com.typesafe.config.Config
import io.radicalbit.nsdb.common.configuration.NSDbConfig.HighLevel._
import io.radicalbit.nsdb.security.NsdbSecurity
import org.json4s.Formats

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.util.{Failure, Success}


trait WebResources extends WsResources with SSLSupport { this: NsdbSecurity =>

  import CORSSupport._
  import VersionHeader._

  implicit def formats: Formats

  def config: Config

  implicit lazy val materializer = ActorMaterializer()
  implicit lazy val dispatcher   = system.dispatcher
  implicit lazy val httpTimeout: Timeout =
    Timeout(config.getDuration("nsdb.http-endpoint.timeout", TimeUnit.SECONDS), TimeUnit.SECONDS)

  def initWebEndpoint(writeCoordinator: ActorRef,
                      readCoordinator: ActorRef,
                      metadataCoordinator: ActorRef,
                      publisher: ActorRef)(implicit logger: LoggingAdapter) =
    authProvider match {
      case Success(provider) =>
        val api: Route = wsResources(publisher, provider) ~ new ApiResources(publisher,
                                                                             readCoordinator,
                                                                             writeCoordinator,
                                                                             metadataCoordinator,
                                                                             provider).apiResources(config)

        val httpExt = akka.http.scaladsl.Http()

        val http: Future[Http.ServerBinding] =
          if (isSSLEnabled) {
            val interface = config.getString(HttpInterface)
            val port      = config.getInt(HttpsPort)
            logger.info(s"Cluster Apis started with https protocol at interface $interface on port $port")
            httpExt.bindAndHandle(withCors(withNSDbVersion(api)), interface, port, connectionContext = serverContext)
          } else {
            val interface = config.getString(HttpInterface)
            val port      = config.getInt(HttpPort)
            logger.info(s"Cluster Apis started with http protocol at interface $interface and port $port")
            httpExt.bindAndHandle(withCors(withNSDbVersion(api)), interface, port)
          }

        scala.sys.addShutdownHook {
          http
            .flatMap(_.unbind())
            .onComplete { _ =>
              system.terminate()
            }
          Await.result(system.whenTerminated, 60 seconds)
        }
      case Failure(ex) =>
        logger.error("error on loading authorization provider", ex)
        System.exit(1)
    }

} 
Example 153
Source File: AkkaHttpRoutesTemplate.scala    From akka-http-circe-json-template   with Apache License 2.0 5 votes vote down vote up
package com.vitorsvieira.http.routes

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.vitorsvieira.http.config.ServerSettingsTemplate._
import com.vitorsvieira.http.model.{ ApiMessage, ApiStatusMessages, ModelTemplate }
import com.vitorsvieira.http.repository.RepositoryTemplate
import de.heikoseeberger.akkahttpcirce.CirceSupport._
import scala.concurrent.Future

object AkkaHttpRoutesTemplate extends BaseRoute with ResponseFactory {

  import io.circe.generic.auto._

  protected def templateDirectives: Route =
    pathPrefix("service1") {
      get {
        path("status") {
          extractRequest { req ⇒
            sendResponse(Future(ApiMessage(ApiStatusMessages.currentStatus())))
          }
        } ~
          path("models" / IntNumber) { (amount) ⇒
            extractRequest { req ⇒
              sendResponse(RepositoryTemplate.getModels(amount))
            }
          } ~
          path("modelsByName" / Segment) { (name) ⇒
            extractRequest { req ⇒
              sendResponse(RepositoryTemplate.getModelsByName(name))
            }
          }
      } ~
        post {
          path("model") {
            decodeRequest {
              entity(as[ModelTemplate]) { model ⇒
                sendResponse(Future(ApiMessage(s"model.vString: ${model.vString} - model.vListInt: ${model.vListInt}")))
              }
            }
          }
        }
    }

  protected lazy val apiV1: Route = api(this.templateDirectives, prefix = true, "v1")

  protected lazy val apiV2: Route =
    api(dsl = logRequestResult("log-service") {
      this.templateDirectives
    }, prefix = true, version = "v2")

  def availableRoutes: Route = apiV1 ~ apiV2

} 
Example 154
Source File: TestRoute.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.testkit

import akka.actor.{Actor, ActorSystem}
import akka.http.scaladsl.server.directives.PathDirectives._
import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route}
import akka.http.scaladsl.settings.RoutingSettings
import akka.testkit.TestActorRef
import org.squbs.unicomplex.{RouteDefinition, WithActorContext, WithWebContext}

import scala.reflect.ClassTag


  def apply[T <: RouteDefinition: ClassTag](webContext: String)(implicit system: ActorSystem): Route = {
    val clazz = implicitly[ClassTag[T]].runtimeClass
    implicit val actorContext = TestActorRef[TestRouteActor].underlyingActor.context
    val routeDef =
      WithWebContext(webContext) {
        WithActorContext {
          clazz.asSubclass(classOf[RouteDefinition]).newInstance()
        }
      }

    implicit val routingSettings = RoutingSettings(system.settings.config)
    implicit val rejectionHandler:RejectionHandler = routeDef.rejectionHandler.getOrElse(RejectionHandler.default)
    implicit val exceptionHandler:ExceptionHandler = routeDef.exceptionHandler.orNull

    if (webContext.length > 0) pathPrefix(separateOnSlashes(webContext)) { Route.seal(routeDef.route) }
    else { Route.seal(routeDef.route) }
  }

  private[testkit] class TestRouteActor extends Actor {
    def receive = {
      case _ =>
    }
  }
} 
Example 155
Source File: RootCtxRouteSpec.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.unicomplex

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Route
import akka.pattern._
import akka.stream.ActorMaterializer
import akka.testkit.{ImplicitSender, TestKit}
import com.typesafe.config.ConfigFactory
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers}
import org.squbs.lifecycle.GracefulStop
import org.squbs.unicomplex.Timeouts._

import scala.concurrent.Await

object RootCtxRouteSpec{

  val classPaths = Array(getClass.getClassLoader.getResource("classpaths/RootCtxRoute").getPath)

  val config = ConfigFactory.parseString(
    s"""
       |default-listener.bind-port = 0
       |squbs {
       |  actorsystem-name = RootCtxRouteSpec
       |  ${JMX.prefixConfig} = true
       |}
    """.stripMargin
  )

  val boot = UnicomplexBoot(config)
    .createUsing {(name, config) => ActorSystem(name, config)}
    .scanComponents(classPaths)
    .initExtensions.start()
}

class RootCtxRouteSpec extends TestKit(
  RootCtxRouteSpec.boot.actorSystem) with FlatSpecLike with Matchers with ImplicitSender with BeforeAndAfterAll {

  implicit val am = ActorMaterializer()

  val portBindings = Await.result((Unicomplex(system).uniActor ? PortBindings).mapTo[Map[String, Int]], awaitMax)
  val port = portBindings("default-listener")

  override def afterAll(): Unit = {
    Unicomplex(system).uniActor ! GracefulStop
  }

  "Route" should "handle request with empty web-context" in {
    Await.result(entityAsString(s"http://127.0.0.1:$port/ping"), awaitMax) should be("pong")
  }
}

class RootRoute extends RouteDefinition {
  override def route: Route = path("ping") {
    complete{"pong"}
  }
} 
Example 156
Source File: PingPongSvc.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.unicomplex.dummycubesvc

import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import org.squbs.lifecycle.{GracefulStop, GracefulStopHelper}
import org.squbs.unicomplex.Timeouts._
import org.squbs.unicomplex.{Ping, Pong, RouteDefinition}

class PingPongSvc extends RouteDefinition{

  def route: Route = path("ping") {
    get {
      onSuccess((context.actorOf(Props(classOf[PingPongClient])) ? "ping").mapTo[String]) {
        case value => complete(value)
      }
    }
  } ~
  path("pong") {
    get {
      onSuccess((context.actorOf(Props(classOf[PingPongClient])) ? "pong").mapTo[String]) {
        case value => complete(value)
      }
    }
  }

}

private class PingPongClient extends Actor with ActorLogging {

  private val pingPongActor = context.actorSelection("/user/DummyCubeSvc/PingPongPlayer")

  def ping(responder: ActorRef): Receive = {
    case Pong => responder ! Pong.toString
  }

  def pong(responder: ActorRef): Receive = {
    case Ping => responder ! Ping.toString
  }

  def receive: Receive = {
    case "ping" => pingPongActor ! Ping
      context.become(ping(sender()))

    case "pong" => pingPongActor ! Pong
      context.become(pong(sender()))
  }

}

class PingPongActor extends Actor with ActorLogging with GracefulStopHelper{

  def receive = {
    case GracefulStop => defaultLeafActorStop

    case Ping => sender ! Pong

    case Pong => sender ! Ping
  }
} 
Example 157
Source File: DummySvc.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.unicomplex.dummysvc

import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import akka.http.scaladsl.server.Route
import akka.pattern.ask
import org.squbs.unicomplex.Timeouts._
import org.squbs.unicomplex._

class DummySvc extends RouteDefinition with WebContext {
  def route: Route =
    get {
      path("msg" / Segment) { param =>
        onSuccess((context.actorOf(Props(classOf[DummyClient])) ? EchoMsg(param)).mapTo[String]) {
          value => complete(value)
        }
      } ~
      path("who") {
        extractClientIP { ip =>
          complete(ip.toString)
        }
      }
    }
}

class Dummy2VersionedSvc extends RouteDefinition with WebContext {
  def route: Route = path("msg" / Segment) {param =>
    get {
      onSuccess((context.actorOf(Props(classOf[DummyClient])) ? EchoMsg(param)).mapTo[String]) {
        case value => complete(value)
      }
    }
  }
}

class Dummy2Svc extends RouteDefinition with WebContext {
  def route: Route = path("msg" / Segment) {param =>
    get {
      onSuccess((context.actorOf(Props(classOf[DummyClient])) ? EchoMsg(param.reverse)).mapTo[String]) {
        case value => complete(value)
      }
    }
  }
}

private class DummyClient extends Actor with ActorLogging {

  private def receiveMsg(responder: ActorRef): Receive = {

    case AppendedMsg(appendedMsg) => context.actorSelection("/user/DummyCube/Prepender") ! EchoMsg(appendedMsg)

    case PrependedMsg(prependedMsg) =>
      responder ! prependedMsg
      context.stop(self)
  }

  def receive: Receive = {
    case msg: EchoMsg =>
      context.actorSelection("/user/DummyCube/Appender") ! msg
      context.become(receiveMsg(sender()))
  }
} 
Example 158
Source File: AkkaHttpClient.scala    From sttp   with Apache License 2.0 5 votes vote down vote up
package sttp.client.akkahttp

import akka.actor.ActorSystem
import akka.event.LoggingAdapter
import akka.http.scaladsl.model.ws.{Message, WebSocketRequest, WebSocketUpgradeResponse}
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.http.scaladsl.server.{ExceptionHandler, RejectionHandler, Route, RoutingLog}
import akka.http.scaladsl.settings.{ClientConnectionSettings, ConnectionPoolSettings, ParserSettings, RoutingSettings}
import akka.http.scaladsl.{Http, HttpsConnectionContext}
import akka.stream.Materializer
import akka.stream.scaladsl.Flow

import scala.concurrent.{ExecutionContext, ExecutionContextExecutor, Future}

trait AkkaHttpClient {
  def singleRequest(
      request: HttpRequest,
      settings: ConnectionPoolSettings
  ): Future[HttpResponse]

  def singleWebsocketRequest[WS_RESULT](
      request: WebSocketRequest,
      clientFlow: Flow[Message, Message, WS_RESULT],
      settings: ClientConnectionSettings
  )(implicit ec: ExecutionContext, mat: Materializer): Future[(WebSocketUpgradeResponse, WS_RESULT)]
}

object AkkaHttpClient {
  def default(
      system: ActorSystem,
      connectionContext: Option[HttpsConnectionContext],
      customLog: Option[LoggingAdapter]
  ): AkkaHttpClient =
    new AkkaHttpClient {
      private val http = Http()(system)

      override def singleRequest(
          request: HttpRequest,
          settings: ConnectionPoolSettings
      ): Future[HttpResponse] = {
        http.singleRequest(
          request,
          connectionContext.getOrElse(http.defaultClientHttpsContext),
          settings,
          customLog.getOrElse(system.log)
        )
      }

      override def singleWebsocketRequest[WS_RESULT](
          request: WebSocketRequest,
          clientFlow: Flow[Message, Message, WS_RESULT],
          settings: ClientConnectionSettings
      )(implicit ec: ExecutionContext, mat: Materializer): Future[(WebSocketUpgradeResponse, WS_RESULT)] = {
        val (wsResponse, wsResult) = http.singleWebSocketRequest(
          request,
          clientFlow,
          connectionContext.getOrElse(http.defaultClientHttpsContext),
          None,
          settings,
          customLog.getOrElse(system.log)
        )
        wsResponse.map((_, wsResult))
      }
    }

  def stubFromAsyncHandler(run: HttpRequest => Future[HttpResponse]): AkkaHttpClient =
    new AkkaHttpClient {
      def singleRequest(request: HttpRequest, settings: ConnectionPoolSettings): Future[HttpResponse] =
        run(request)

      override def singleWebsocketRequest[WS_RESULT](
          request: WebSocketRequest,
          clientFlow: Flow[Message, Message, WS_RESULT],
          settings: ClientConnectionSettings
      )(implicit ec: ExecutionContext, mat: Materializer): Future[(WebSocketUpgradeResponse, WS_RESULT)] =
        Future.failed(new RuntimeException("Websockets are not supported"))
    }

  def stubFromRoute(route: Route)(implicit
      routingSettings: RoutingSettings,
      parserSettings: ParserSettings,
      materializer: Materializer,
      routingLog: RoutingLog,
      executionContext: ExecutionContextExecutor = null,
      rejectionHandler: RejectionHandler = RejectionHandler.default,
      exceptionHandler: ExceptionHandler = null
  ): AkkaHttpClient = stubFromAsyncHandler(Route.asyncHandler(route))
} 
Example 159
Source File: AkkaHttpRouteBackendTest.scala    From sttp   with Apache License 2.0 5 votes vote down vote up
package sttp.client.akkahttp

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import org.scalatest.BeforeAndAfterAll
import sttp.client.{NothingT, SttpBackend}
import sttp.model.StatusCode

import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AsyncWordSpec

class AkkaHttpRouteBackendTest extends AsyncWordSpec with Matchers with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem()
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  override protected def afterAll(): Unit = {
    Await.result(system.terminate(), 5.seconds)
  }

  val backend: SttpBackend[Future, Nothing, NothingT] = {
    AkkaHttpBackend.usingClient(system, http = AkkaHttpClient.stubFromRoute(Routes.route))
  }

  import sttp.client._

  "matched route" should {

    "respond" in {
      backend.send(basicRequest.get(uri"http://localhost/hello")).map { response =>
        response.code shouldBe StatusCode.Ok
        response.body.right.get shouldBe "Hello, world!"
      }
    }
  }

  "unmatched route" should {
    "respond with 404" in {
      backend.send(basicRequest.get(uri"http://localhost/not-matching")).map { response =>
        response.code shouldBe StatusCode.NotFound
        response.body.left.get shouldBe "The requested resource could not be found."
      }
    }
  }

}

object Routes {
  import akka.http.scaladsl.server.Directives._

  val route: Route =
    pathPrefix("hello") {
      complete("Hello, world!")
    }
} 
Example 160
Source File: StatsEndpoint.scala    From akka-kubernetes-tests   with Apache License 2.0 5 votes vote down vote up
package akka.kubernetes.soak
import akka.actor.{ActorRef, ActorSystem}
import akka.event.Logging
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.{Directives, Route}
import spray.json.DefaultJsonProtocol
import akka.pattern.ask
import akka.util.Timeout

import scala.concurrent.duration._
import scala.util.{Failure, Success}

// collect your json format instances into a support trait:
trait StatsJsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val testResultFormat = jsonFormat2(TestResult)
  implicit val testResultsFormat = jsonFormat7(TestResults)
}

class StatsEndpoint(system: ActorSystem, client: ActorRef) extends Directives with StatsJsonSupport {
  private implicit val askTimeout = Timeout(5.seconds)
  private val log = Logging(system, getClass)

  val route: Route =
    path("stats") {
      get {
        onComplete(client.ask(GetTestResults()).mapTo[TestResults]) {
          case Failure(t) =>
            log.error(t, "Failed to get test results")
            complete(StatusCodes.InternalServerError)
          case Success(value) =>
            complete(value)
        }
      }
    }

} 
Example 161
Source File: Routes.scala    From akka-ddd-cqrs-es-example   with MIT License 5 votes vote down vote up
package com.github.j5ik2o.bank.adaptor.controller

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity, HttpResponse }
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.Materializer
import cats.syntax.either._
import com.github.j5ik2o.bank.adaptor.generator.IdGenerator
import com.github.j5ik2o.bank.domain.model.BankAccountId
import com.github.j5ik2o.bank.useCase.{ BankAccountAggregateUseCase, BankAccountReadModelUseCase }
import org.hashids.Hashids

object Routes {

  trait ResponseJson {
    val isSuccessful: Boolean
    val errorMessages: Seq[String]
  }

  case class OpenBankAccountRequestJson(name: String)

  case class OpenBankAccountResponseJson(id: String, errorMessages: Seq[String] = Seq.empty) extends ResponseJson {
    override val isSuccessful: Boolean = errorMessages.isEmpty
  }

  case class UpdateBankAccountRequestJson(name: String)

  case class UpdateBankAccountResponseJson(id: String, errorMessages: Seq[String] = Seq.empty) extends ResponseJson {
    override val isSuccessful: Boolean = errorMessages.isEmpty
  }

  case class AddBankAccountEventRequestJson(`type`: String, amount: Long, currencyCode: String)

  case class AddBankAccountEventResponseJson(id: String, errorMessages: Seq[String] = Seq.empty) extends ResponseJson {
    override val isSuccessful: Boolean = errorMessages.isEmpty
  }

  case class CloseBankAccountRequestJson(id: String)

  case class CloseBankAccountResponseJson(id: String, errorMessages: Seq[String] = Seq.empty) extends ResponseJson {
    override val isSuccessful: Boolean = errorMessages.isEmpty
  }

  case class BankAccountEventJson(`type`: String, amount: Long, currencyCode: String, createAt: Long)

  case class ResolveBankAccountEventsResponseJson(id: String,
                                                  values: Seq[BankAccountEventJson],
                                                  errorMessages: Seq[String] = Seq.empty)
      extends ResponseJson {
    override val isSuccessful: Boolean = errorMessages.isEmpty
  }

  case class ValidationErrorsResponseJson(errorMessages: Seq[String]) extends ResponseJson {
    override val isSuccessful: Boolean = false
  }

  implicit class HashidsStringOps(val self: String) extends AnyVal {
    def decodeFromHashid(implicit hashIds: Hashids): Either[Throwable, Long] = {
      Either.catchNonFatal(hashIds.decode(self)(0))
    }
  }

  implicit class HashidsLongOps(val self: Long) extends AnyVal {
    def encodeToHashid(implicit hashIds: Hashids): Either[Throwable, String] =
      Either.catchNonFatal(hashIds.encode(self))
  }

}

case class Routes(bankAccountIdGenerator: IdGenerator[BankAccountId],
                  bankAccountAggregateUseCase: BankAccountAggregateUseCase,
                  bankAccountReadModelUseCase: BankAccountReadModelUseCase)(
    implicit system: ActorSystem,
    mat: Materializer
) extends BankAccountController {

  implicit val ec = system.dispatcher

  def root: Route = RouteLogging.default.httpLogRequestResult {
    pathEndOrSingleSlash {
      get {
        index()
      }
    } ~ toBankAccountRoutes
  }

  private def index() = complete(
    HttpResponse(
      entity = HttpEntity(
        ContentTypes.`text/plain(UTF-8)`,
        "Wellcome to Bank API"
      )
    )
  )

} 
Example 162
Source File: Hello.scala    From sbt-guardrail   with MIT License 5 votes vote down vote up
package helloworld

import scala.concurrent.Future
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.stream.Materializer
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import cats.implicits._
import com.example.clients.petstore.user.UserClient

object Hello {

  def buildUserClient(): UserClient = {
    import scala.concurrent.ExecutionContext.Implicits.global

    val server = buildServer()

    implicit val actorSys = ActorSystem()
    implicit val materializer = ActorMaterializer()

    UserClient.httpClient(server)
  }

  private def buildServer(): HttpRequest => Future[HttpResponse] = {
    import com.example.servers.petstore.user._
    import akka.http.scaladsl.server.Route
    import akka.http.scaladsl.settings.RoutingSettings

    implicit val actorSys = ActorSystem()
    implicit val materializer = ActorMaterializer()
    implicit val routingSettings = RoutingSettings(actorSys)

    Route.asyncHandler(
      UserResource.routes(new DummyUserHandler())
    )
  }
}

class DummyUserHandler
  extends com.example.servers.petstore.user.UserHandler {

  import com.example.servers.petstore.user._
  import com.example.servers.petstore.definitions._
  import scala.collection._

  def createUser(respond: UserResource.CreateUserResponse.type)(body: User): scala.concurrent.Future[UserResource.CreateUserResponse] = ???
  def createUsersWithArrayInput(respond: UserResource.CreateUsersWithArrayInputResponse.type)(body: Vector[User]): scala.concurrent.Future[UserResource.CreateUsersWithArrayInputResponse] = ???
  def createUsersWithListInput(respond: UserResource.CreateUsersWithListInputResponse.type)(body: Vector[User]): scala.concurrent.Future[UserResource.CreateUsersWithListInputResponse] = ???
  def loginUser(respond: UserResource.LoginUserResponse.type)(username: String, password: String): scala.concurrent.Future[UserResource.LoginUserResponse] = ???
  def logoutUser(respond: UserResource.LogoutUserResponse.type)(): scala.concurrent.Future[UserResource.LogoutUserResponse] = ???
  def getUserByName(respond: UserResource.GetUserByNameResponse.type)(username: String): scala.concurrent.Future[UserResource.GetUserByNameResponse] = {
    val user = new User(
      id = Some(1234),
      username = Some(username),
      firstName = Some("First"),
      lastName = Some("Last"),
      email = Some(username + "@example.com"))
    Future.successful(respond.OK(user))
  }
  def updateUser(respond: UserResource.UpdateUserResponse.type)(username: String, body: User): scala.concurrent.Future[UserResource.UpdateUserResponse] = ???
  def deleteUser(respond: UserResource.DeleteUserResponse.type)(username: String): scala.concurrent.Future[UserResource.DeleteUserResponse] = ???
} 
Example 163
Source File: EchoListService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.echolist

import akka.http.scaladsl.server.{Directives, Route}
import com.example.akka.DefaultJsonFormats
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import javax.ws.rs.{Consumes, POST, Path, Produces}
import pl.iterators.kebs.json.KebsSpray
import spray.json.RootJsonFormat

@Path("/echolist")
object EchoListService extends Directives with DefaultJsonFormats with KebsSpray {

  case class EchoList(listName: String, values: Seq[String])

  implicit val echoListFormat: RootJsonFormat[EchoList] = jsonFormatN[EchoList]

  val route: Route = echo

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Echo List", description = "Echo List",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[EchoList])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Echo List",
        content = Array(new Content(schema = new Schema(implementation = classOf[EchoList])))),
      new ApiResponse(responseCode = "400", description = "Bad Request"))
  )
  def echo: Route =
    path("echolist") {
      post {
        entity(as[EchoList]) { request =>
          complete(request)
        }
      }
    }

} 
Example 164
Source File: AddService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.add

import javax.ws.rs.{Consumes, POST, Path, Produces}
import akka.actor.ActorRef
import akka.http.scaladsl.server.{Directives, Route}
import akka.pattern.ask
import akka.util.Timeout
import com.example.akka.DefaultJsonFormats
import com.example.akka.add.AddActor._
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import spray.json.RootJsonFormat

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt

@Path("/add")
class AddService(addActor: ActorRef)(implicit executionContext: ExecutionContext)
  extends Directives with DefaultJsonFormats {

  implicit val timeout: Timeout = Timeout(2.seconds)

  implicit val requestFormat: RootJsonFormat[AddRequest] = jsonFormat1(AddRequest)
  implicit val responseFormat: RootJsonFormat[AddResponse] = jsonFormat1(AddResponse)

  val route: Route = add

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Add integers", description = "Add integers",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[AddRequest])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Add response",
        content = Array(new Content(schema = new Schema(implementation = classOf[AddResponse])))),
      new ApiResponse(responseCode = "500", description = "Internal server error"))
  )
  def add: Route =
    path("add") {
      post {
        entity(as[AddRequest]) { request =>
          complete { (addActor ? request).mapTo[AddResponse] }
        }
      }
    }

} 
Example 165
Source File: EchoEnumeratumService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.echoenumeratum

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.{Directives, Route}
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import javax.ws.rs.{Consumes, POST, Path, Produces}
import pl.iterators.kebs.json.{KebsEnumFormats, KebsSpray}
import spray.json.{DefaultJsonProtocol, RootJsonFormat}

@Path("/echoenumeratum")
object EchoEnumeratumService extends Directives with SprayJsonSupport with DefaultJsonProtocol
  with KebsSpray with KebsEnumFormats {

  case class EchoEnumeratum(enumValue: SizeEnum)

  implicit val echoEnumeratumFormat: RootJsonFormat[EchoEnumeratum] = jsonFormatN[EchoEnumeratum]

  val route: Route = echo

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Echo Enumeratum", description = "Echo Enumeratum",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnumeratum])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Echo Enumeratum",
        content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnumeratum])))),
      new ApiResponse(responseCode = "400", description = "Bad Request"))
  )
  def echo: Route =
    path("echoenumeratum") {
      post {
        entity(as[EchoEnumeratum]) { request =>
          complete(request)
        }
      }
    }

} 
Example 166
Source File: AddOptionService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.addoption

import javax.ws.rs.{Consumes, POST, Path, Produces}
import akka.actor.ActorRef
import akka.http.scaladsl.server.{Directives, Route}
import akka.pattern.ask
import akka.util.Timeout
import com.example.akka.DefaultJsonFormats
import com.example.akka.addoption.AddOptionActor._
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import spray.json.RootJsonFormat

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt

@Path("/addOption")
class AddOptionService(addActor: ActorRef)(implicit executionContext: ExecutionContext)
  extends Directives with DefaultJsonFormats {

  implicit val timeout: Timeout = Timeout(2.seconds)

  implicit val requestFormat: RootJsonFormat[AddOptionRequest] = jsonFormat2(AddOptionRequest)
  implicit val responseFormat: RootJsonFormat[AddOptionResponse] = jsonFormat1(AddOptionResponse)

  val route: Route = addOption

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Add integers", description = "Add integers",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[AddOptionRequest])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Add response",
        content = Array(new Content(schema = new Schema(implementation = classOf[AddOptionResponse])))),
      new ApiResponse(responseCode = "500", description = "Internal server error"))
  )
  def addOption: Route =
    path("addOption") {
      post {
        entity(as[AddOptionRequest]) { request =>
          complete { (addActor ? request).mapTo[AddOptionResponse] }
        }
      }
    }

} 
Example 167
Source File: HelloService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.hello

import javax.ws.rs.{GET, Path, Produces}
import akka.actor.ActorRef
import akka.http.scaladsl.server.{Directives, Route}
import akka.pattern.ask
import akka.util.Timeout
import com.example.akka.DefaultJsonFormats
import com.example.akka.hello.HelloActor._
import io.swagger.v3.oas.annotations.enums.ParameterIn
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.{Operation, Parameter}
import javax.ws.rs.core.MediaType
import spray.json.RootJsonFormat

import scala.concurrent.ExecutionContext
import scala.concurrent.duration.DurationInt

@Path("/hello")
class HelloService(hello: ActorRef)(implicit executionContext: ExecutionContext)
  extends Directives with DefaultJsonFormats {

  implicit val timeout: Timeout = Timeout(2.seconds)
  implicit val greetingFormat: RootJsonFormat[Greeting] = jsonFormat1(Greeting)

  val route: Route =
    getHello ~
    getHelloSegment

  @GET
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Return Hello greeting (anonymous)", description = "Return Hello greeting for anonymous request",
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Hello response",
        content = Array(new Content(schema = new Schema(implementation = classOf[Greeting])))),
      new ApiResponse(responseCode = "500", description = "Internal server error"))
  )
  def getHello: Route =
    path("hello") {
      get {
        complete { (hello ? AnonymousHello).mapTo[Greeting] }
      }
    }

  @GET
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Return Hello greeting", description = "Return Hello greeting for named user",
    parameters = Array(new Parameter(name = "name", in = ParameterIn.PATH, description = "user name")),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Hello response",
        content = Array(new Content(schema = new Schema(implementation = classOf[Greeting])))),
      new ApiResponse(responseCode = "500", description = "Internal server error"))
  )
  def getHelloSegment: Route =
    path("hello" / Segment) { name =>
      get {
        complete { (hello ? Hello(name)).mapTo[Greeting] }
      }
    }
} 
Example 168
Source File: EchoEnumService.scala    From swagger-akka-http-sample   with Apache License 2.0 5 votes vote down vote up
package com.example.akka.echoenum

import akka.http.scaladsl.server.{Directives, Route}
import com.example.akka.DefaultJsonFormats
import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.module.scala.JsonScalaEnumeration
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.{Content, Schema}
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import javax.ws.rs.core.MediaType
import javax.ws.rs.{Consumes, POST, Path, Produces}
import spray.json.{DeserializationException, JsString, JsValue, RootJsonFormat}

@Path("/echoenum")
object EchoEnumService extends Directives with DefaultJsonFormats {

  //case class EchoEnum(@Schema(required = true, `type` = "string", allowableValues = Array("TALL", "GRANDE", "VENTI"))
  //                    enumValue: SizeEnum.Value)
  class SizeEnumTypeClass extends TypeReference[SizeEnum.type]
  case class EchoEnum(@JsonScalaEnumeration(classOf[SizeEnumTypeClass]) enumValue: SizeEnum.Value)

  implicit val enumFormat: RootJsonFormat[SizeEnum.Value] =
    new RootJsonFormat[SizeEnum.Value] {
      def write(obj: SizeEnum.Value): JsValue = JsString(obj.toString)
      def read(json: JsValue): SizeEnum.Value = {
        json match {
          case JsString(txt) => SizeEnum.withName(txt)
          case somethingElse => throw DeserializationException(s"Expected a value from enum $SizeEnum instead of $somethingElse")
        }
      }
    }
  implicit val echoEnumFormat: RootJsonFormat[EchoEnum] = jsonFormat1(EchoEnum)

  val route: Route = echo

  @POST
  @Consumes(Array(MediaType.APPLICATION_JSON))
  @Produces(Array(MediaType.APPLICATION_JSON))
  @Operation(summary = "Echo Enum", description = "Echo Enum",
    requestBody = new RequestBody(content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnum])))),
    responses = Array(
      new ApiResponse(responseCode = "200", description = "Echo Enum",
        content = Array(new Content(schema = new Schema(implementation = classOf[EchoEnum])))),
      new ApiResponse(responseCode = "400", description = "Bad Request"))
  )
  def echo: Route =
    path("echoenum") {
      post {
        entity(as[EchoEnum]) { request =>
          complete(request)
        }
      }
    }

} 
Example 169
Source File: RoutedService.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http.routing

import akka.ConfigurationException
import akka.actor._
import akka.http.scaladsl.server.{Route, RouteConcatenation}

import scala.concurrent.ExecutionContext


  private def loadRoutes(routeEndpoints: Seq[Class[_ <: RoutedEndpoints]]): Seq[RoutedEndpoints] = {

    log.info("Setting up all of the routes")
    val newRoutes =
      for {
        route <- routeEndpoints
      } yield {
        val args = List(classOf[ActorSystem] -> context.system, classOf[ExecutionContext] -> context.dispatcher)

        context.system.asInstanceOf[ExtendedActorSystem].dynamicAccess
          .createInstanceFor[RoutedEndpoints](route.getName, args).map({
          case route =>
            route
        }).recover({
          case e => throw new ConfigurationException(
            "RoutedEndpoints can't be loaded [" + route.getName +
              "] due to [" + e.toString + "]", e)
        }).get
      }

    newRoutes.toSeq
  }
} 
Example 170
Source File: BaseDirectivesSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http

import akka.http.scaladsl.marshalling._
import akka.http.scaladsl.model.MediaTypes._
import akka.http.scaladsl.model.headers.Accept
import akka.http.scaladsl.model.{MediaType, MediaTypes}
import akka.http.scaladsl.server.{ContentNegotiator, Route, UnacceptedResponseContentTypeRejection}
import com.github.vonnagy.service.container.Specs2RouteTest
import org.specs2.mutable.Specification


class BaseDirectivesSpec extends Specification with BaseDirectives with DefaultMarshallers with Specs2RouteTest {

  val `application/vnd.com.github.vonnagy.container.health-v1+json` =
    MediaType.custom("application/vnd.com.github.vonnagy.container.health-v1+json", false)

  "The base directives" should {

    "allow the use of the `acceptableMediaTypes` directive" in {

      import MediaTypes._

      implicit val marsh: ToEntityMarshaller[Seq[String]] = jsonMarshaller

      implicit val vndMarsh: ToEntityMarshaller[String] =
        Marshaller.StringMarshaller.wrap(`application/vnd.com.github.vonnagy.container.health-v1+json`)(_.toString)

      val route: Route =
        path("app-json") {
          acceptableMediaTypes(`application/json`, `application/vnd.com.github.vonnagy.container.health-v1+json`) {
            complete(Seq())
          }
        } ~
          path("app-custom") {
            acceptableMediaTypes(`application/json`, `application/vnd.com.github.vonnagy.container.health-v1+json`) {
              complete("[]")
            }
          }

      Get("/app-json")
        .withHeaders(Accept(`application/json`, `application/vnd.com.github.vonnagy.container.health-v1+json`)) ~>
        route ~> check {
        responseAs[String] === "[]"
        mediaType === MediaTypes.`application/json`
      }

      Get("/app-custom")
        .withHeaders(Accept(`application/vnd.com.github.vonnagy.container.health-v1+json`, `application/json`)) ~>
        route ~> check {
        responseAs[String] === "[]"
        mediaType === `application/vnd.com.github.vonnagy.container.health-v1+json`
      }

      Get("/app-json").withHeaders(Accept(`text/plain`)) ~> route ~> check {
        rejection === UnacceptedResponseContentTypeRejection(Set(ContentNegotiator.Alternative(`application/json`),
          ContentNegotiator.Alternative(`application/vnd.com.github.vonnagy.container.health-v1+json`)))
      }
    }
  }

  "allow for the use of json response type" in {

    implicit val marsh: ToEntityMarshaller[Seq[String]] = jsonMarshaller

    Get() ~> {
      complete(Seq())
    } ~> check {
      mediaType === `application/json`
    }
  }

  "allow for the use of plain response type" in {

    Get() ~> {
      complete("[]")
    } ~> check {
      mediaType === `text/plain`
    }

  }

} 
Example 171
Source File: RoutingHandlerSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http.routing

import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.ContentTypes._
import akka.http.scaladsl.server.{Directives, MalformedRequestContentRejection, MissingCookieRejection, Route}
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.routing.Rejection.DuplicateRejection
import org.specs2.mutable.Specification


class RoutingHandlerSpec extends Specification with Specs2RouteTest with Directives {

  val handler = new RoutingHandler {
    def conf = system.settings.config
  }

  val dummyRoute =
    pathPrefix("test") {
      get {
        path("duplicate") {
          reject(DuplicateRejection("test"))
        } ~
        path("malformed") {
          reject(MalformedRequestContentRejection("test", new Exception("test")))
        } ~
        path("cookie") {
          reject(MissingCookieRejection("test"))
        } ~
        path("exception") {
          throw new NullPointerException("test")
        }
      }
    }

  "the routing handler" should {

    "provide custom rejection handlers" in {
      implicit val rejHandler = handler.rejectionHandler
      val sr = Route.seal(dummyRoute)

      Get("/test/duplicate") ~> sr ~> check {
        status must be equalTo BadRequest
        responseAs[String] must be equalTo(
          """{"code":400,"message":"The request contains bad syntax or cannot be fulfilled.","details":"\"test\""}""")
      }

      Get("/test/malformed") ~> sr ~> check {
        status must be equalTo UnprocessableEntity
        responseAs[String] must be equalTo(
          """{"code":422,"message":"The request was well-formed but was unable to be followed due to semantic errors.","details":"\"test\""}""")
      }
    }

    "use the default rejection handler as a fallback" in {
      implicit val rejHandler = handler.rejectionHandler
      val sr = Route.seal(dummyRoute)

      Get("/test/cookie") ~> sr ~> check {
        status must be equalTo BadRequest
        responseAs[String] must be equalTo(
          """{"code":400,"message":"The request contains bad syntax or cannot be fulfilled.","details":"Request is missing required cookie 'test'"}""")
      }
    }

    "provide custom exception handlers" in {
      implicit val exHandler = handler.exceptionHandler
      val sr = Route.seal(dummyRoute)

      Get("/test/exception") ~> sr ~> check {
        status must be equalTo InternalServerError
        contentType must be equalTo `application/json`
        responseAs[String] must be equalTo(
          """{"code":500,"message":"There was an internal server error.","details":"Something bad happened"}""")
      }
 }

  }
} 
Example 172
Source File: RoutedServiceSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http.routing

import akka.actor._
import akka.http.scaladsl.model.{HttpEntity, MediaTypes, StatusCodes}
import akka.http.scaladsl.server.{Directives, Route}
import akka.testkit.{TestActorRef, TestProbe}
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.{DefaultMarshallers, RejectionResponse}
import org.specs2.mutable.Specification

class RoutedServiceSpec extends Specification with Directives with Specs2RouteTest {

  case class TestEntity(id: Int, name: String)

  val probe = new TestProbe(system)
  val httpAct = TestActorRef(Props(new Actor with RoutedService with DefaultMarshallers {
    def receive = routeReceive
  }), "http")

  val svc = httpAct.underlyingActor.asInstanceOf[RoutedService]

  def echoComplete[T]: T => Route = { x ⇒ complete(x.toString) }

  "The RoutedService" should {

    "allow for routes to be added after the system is already loaded" in {
      // This should create the actor and register the endpoints
      val r = new RoutedEndpoints {
        def route = {
          path("test2") {
            complete("test2")
          }
        }
      }

      probe.send(httpAct, AddRoute(r))
      probe.expectMsg(RouteAdded)

      Get("/test2") ~> svc.buildRoute(svc.routes) ~> check {
        responseAs[String] must be equalTo "test2"
      }
    }

    "respond with UnprocessableEntity for requests resulting in a MalformedFormFieldRejection" in {

      implicit val unmarsh = svc.jsonUnmarshaller[TestEntity]
      implicit val rejMarsh = svc.jsonUnmarshaller[RejectionResponse]

      val postRoute = new RoutedEndpoints {
        def route = {
          post {
            path("test4") {
              entity(as[TestEntity]) {
                echoComplete
              }
            }
          }
        }
      }

      probe.send(httpAct, AddRoute(postRoute))
      probe.expectMsg(RouteAdded)

      import svc.defaultJsonFormats
      val ent = TestEntity(100, "product")

      Post("/test4", HttpEntity(MediaTypes.`application/json`, svc.serialization.write(ent))) ~>
        handleRejections(svc.rejectionHandler)(svc.buildRoute(svc.routes)) ~> check {
        status === StatusCodes.UnprocessableEntity
        mediaType === MediaTypes.`application/json`
        responseAs[RejectionResponse] must not beNull
      }
    }

    "respond with RejectionResponse for requests that error out" in {

      implicit val rejMarsh = svc.jsonUnmarshaller[RejectionResponse]

      val postRoute = new RoutedEndpoints {
        def route = {
          get {
            path("test5") { ctx => throw new Exception("test") }
          }
        }
      }

      probe.send(httpAct, AddRoute(postRoute))
      probe.expectMsg(RouteAdded)

      Get("/test5") ~>
        Route.seal(svc.buildRoute(svc.routes))(svc.routeSettings,
          exceptionHandler = svc.exceptionHandler,
          rejectionHandler = svc.rejectionHandler) ~> check {

        mediaType === MediaTypes.`application/json`
        responseAs[RejectionResponse] must not beNull
      }
    }
  }

} 
Example 173
Source File: SchedulerRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api

import akka.http.scaladsl.model.StatusCodes.OK
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import io.vamp.common.Namespace
import io.vamp.common.akka._
import io.vamp.common.http.HttpApiDirectives
import io.vamp.operation.controller.SchedulerController

object SchedulerRoute {
  val path: String = "scheduler"
}

trait SchedulerRoute extends AbstractRoute with SchedulerController with ExecutionContextProvider {
  this: HttpApiDirectives ⇒

  def schedulerRoutes(implicit namespace: Namespace, timeout: Timeout): Route = get {
    pathPrefix(SchedulerRoute.path) {
      path("nodes") {
        pageAndPerPage() { (page, perPage) ⇒
          onSuccess(nodes(page, perPage)) {
            result ⇒ respondWith(OK, result)
          }
        }
      } ~ path("routing") {
        pageAndPerPage() { (page, perPage) ⇒
          parameters('selector.?) { selector ⇒
            onSuccess(routing(selector)(page, perPage)) {
              result ⇒ respondWith(OK, result)
            }
          }
        }
      }
    }
  }
} 
Example 174
Source File: WebSocketRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api.ws

import java.util.UUID

import akka.actor.PoisonPill
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.ws.{ Message, TextMessage }
import akka.http.scaladsl.server.Route
import akka.stream._
import akka.stream.scaladsl.{ Flow, Sink, Source }
import akka.util.Timeout
import io.vamp.common.akka.IoC._
import io.vamp.common.http.{ HttpApiDirectives, HttpApiHandlers, TerminateFlowStage }
import io.vamp.common.{ Config, Namespace }
import io.vamp.http_api.ws.WebSocketActor.{ SessionClosed, SessionEvent, SessionOpened, SessionRequest }
import io.vamp.http_api.{ AbstractRoute, LogDirective }

import scala.concurrent.Future

trait WebSocketRoute extends AbstractRoute with WebSocketMarshaller with HttpApiHandlers {
  this: HttpApiDirectives with LogDirective ⇒

  implicit def materializer: Materializer

  private lazy val limit = Config.int("vamp.http-api.websocket.stream-limit")

  protected def websocketApiHandler(implicit namespace: Namespace, timeout: Timeout): Route

  def websocketRoutes(implicit namespace: Namespace, timeout: Timeout) = {
    pathEndOrSingleSlash {
      get {
        extractRequest { request ⇒
          handleWebSocketMessages {
            websocket(request)
          }
        }
      }
    }
  }

  protected def filterWebSocketOutput(message: AnyRef)(implicit namespace: Namespace, timeout: Timeout): Future[Boolean] = Future.successful(true)

  private def apiHandler(implicit namespace: Namespace, timeout: Timeout) = Route.asyncHandler(log {
    websocketApiHandler
  })

  private def websocket(origin: HttpRequest)(implicit namespace: Namespace, timeout: Timeout): Flow[AnyRef, Message, Any] = {
    val id = UUID.randomUUID()

    val in = Flow[AnyRef].collect {
      case TextMessage.Strict(message)  ⇒ Future.successful(message)
      case TextMessage.Streamed(stream) ⇒ stream.limit(limit()).completionTimeout(timeout.duration).runFold("")(_ + _)
    }.mapAsync(parallelism = 3)(identity)
      .mapConcat(unmarshall)
      .map(SessionRequest(apiHandler, id, origin, _))
      .to(Sink.actorRef[SessionEvent](actorFor[WebSocketActor], SessionClosed(id)))

    val out = Source.actorRef[AnyRef](16, OverflowStrategy.dropHead)
      .mapMaterializedValue(actorFor[WebSocketActor] ! SessionOpened(id, _))
      .via(new TerminateFlowStage[AnyRef](_ == PoisonPill))
      .mapAsync(parallelism = 3)(message ⇒ filterWebSocketOutput(message).map(f ⇒ f → message))
      .collect { case (true, m) ⇒ m }
      .map(message ⇒ TextMessage.Strict(marshall(message)))

    Flow.fromSinkAndSource(in, out)
  }
} 
Example 175
Source File: LogApiRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api

import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling
import akka.http.scaladsl.server.Route
import com.typesafe.scalalogging.LazyLogging
import io.vamp.common.{ ConfigMagnet, Namespace }
import io.vamp.common.http.HttpApiDirectives
import io.vamp.operation.controller.LogApiController

import scala.concurrent.duration.FiniteDuration

trait LogApiRoute extends AbstractRoute with LogApiController with EventStreamMarshalling with LazyLogging {
  this: HttpApiDirectives ⇒

  def sseKeepAliveTimeout: ConfigMagnet[FiniteDuration]

  def sseLogRoutes(implicit namespace: Namespace): Route = path("logs" | "log") {
    pathEndOrSingleSlash {
      get {
        parameters('level.as[String] ? "") { level ⇒
          parameters('logger.as[String] ? "") { loggerP ⇒
            logger.info(s"log route called with $level $loggerP")
            complete(sourceLog(level, if (loggerP.trim.isEmpty) None else Option(loggerP), sseKeepAliveTimeout()))
          }
        }
      }
    }
  }
} 
Example 176
Source File: HealthRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api

import akka.http.scaladsl.model.StatusCodes.{ NotFound, OK }
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import io.vamp.common.Namespace
import io.vamp.common.http.HttpApiDirectives
import io.vamp.operation.controller.HealthController

import io.vamp.model.artifact.{ Gateway, Deployment }

object HealthRoute {
  val path = "health"
}

trait HealthRoute extends AbstractRoute with HealthController {
  this: HttpApiDirectives ⇒

  def healthRoutes(implicit namespace: Namespace, timeout: Timeout): Route = pathPrefix(HealthRoute.path) {
    get {
      parameters("window".?) { window ⇒
        path(Gateway.kind / Segment) { gateway ⇒
          pathEndOrSingleSlash {
            onSuccess(gatewayHealth(gateway)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Gateway.kind / Segment / "routes" / Segment) { (gateway, route) ⇒
          pathEndOrSingleSlash {
            onSuccess(routeHealth(gateway, route)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment) { deployment ⇒
          pathEndOrSingleSlash {
            onSuccess(deploymentHealth(deployment)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment) { (deployment, cluster) ⇒
          pathEndOrSingleSlash {
            onSuccess(clusterHealth(deployment, cluster)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment / "services" / Segment) { (deployment, cluster, service) ⇒
          pathEndOrSingleSlash {
            onSuccess(serviceHealth(deployment, cluster, service)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment / "services" / Segment / "instances" / Segment) { (deployment, cluster, service, instance) ⇒
          pathEndOrSingleSlash {
            onSuccess(instanceHealth(deployment, cluster, service, instance)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        }
      }
    }
  }
} 
Example 177
Source File: MetricsRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api

import akka.http.scaladsl.model.StatusCodes.{ NotFound, OK }
import akka.http.scaladsl.server.Route
import akka.util.Timeout
import io.vamp.common.Namespace
import io.vamp.common.http.HttpApiDirectives
import io.vamp.operation.controller.MetricsController

import io.vamp.model.artifact.{ Gateway, Deployment }

object MetricsRoute {
  val path = "metrics"
}

trait MetricsRoute extends AbstractRoute with MetricsController {
  this: HttpApiDirectives ⇒

  def metricsRoutes(implicit namespace: Namespace, timeout: Timeout): Route = pathPrefix(MetricsRoute.path) {
    get {
      parameters("window".?) { window ⇒
        path(Gateway.kind / Segment / Segment) { (gateway, metrics) ⇒
          pathEndOrSingleSlash {
            onSuccess(gatewayMetrics(gateway, metrics)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Gateway.kind / Segment / "routes" / Segment / Segment) { (gateway, route, metrics) ⇒
          pathEndOrSingleSlash {
            onSuccess(routeMetrics(gateway, route, metrics)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment / "ports" / Segment / Segment) { (deployment, cluster, port, metrics) ⇒
          pathEndOrSingleSlash {
            onSuccess(clusterMetrics(deployment, cluster, port, metrics)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment / "services" / Segment / "ports" / Segment / Segment) { (deployment, cluster, service, port, metrics) ⇒
          pathEndOrSingleSlash {
            onSuccess(serviceMetrics(deployment, cluster, service, port, metrics)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        } ~ path(Deployment.kind / Segment / "clusters" / Segment / "services" / Segment / "instances" / Segment / "ports" / Segment / Segment) { (deployment, cluster, service, instance, port, metrics) ⇒
          pathEndOrSingleSlash {
            onSuccess(instanceMetrics(deployment, cluster, service, instance, port, metrics)(window)) {
              case Some(result) ⇒ respondWith(OK, result)
              case _            ⇒ respondWith(NotFound, None)
            }
          }
        }
      }
    }
  }
} 
Example 178
Source File: ProxyRoute.scala    From vamp   with Apache License 2.0 5 votes vote down vote up
package io.vamp.http_api

import akka.http.scaladsl.model.StatusCodes.BadGateway
import akka.http.scaladsl.model.ws.UpgradeToWebSocket
import akka.http.scaladsl.server.{ RequestContext, Route, RouteResult }
import akka.stream.Materializer
import akka.util.Timeout
import io.vamp.common.Namespace
import io.vamp.common.http.HttpApiDirectives
import io.vamp.model.artifact.{ Gateway, Deployment, Workflow }
import io.vamp.operation.controller.ProxyController

import scala.concurrent.Future
import scala.util.Try

trait ProxyRoute extends AbstractRoute with ProxyController {
  this: HttpApiDirectives ⇒

  implicit def materializer: Materializer

  def proxyRoute(implicit namespace: Namespace, timeout: Timeout): Route =
    path("host" / Segment / "port" / Segment / RemainingPath) {
      (host, port, path) ⇒ Try(handle(hostPortProxy(host, port.toInt, path))).getOrElse(complete(BadGateway))
    } ~ path(Gateway.kind / Segment / Segment / Segment / RemainingPath) {
      (name1, name2, name3, path) ⇒ handle(gatewayProxy(s"$name1/$name2/$name3", path, skip = true))
    } ~ path(Gateway.kind / Segment / Segment / RemainingPath) {
      (name1, name2, path) ⇒ handle(gatewayProxy(s"$name1/$name2", path, skip = true))
    } ~ path(Gateway.kind / Segment / RemainingPath) {
      (gateway, path) ⇒ handle(gatewayProxy(gateway, path, skip = false))
    } ~ path(Workflow.kind / Segment / "instances" / Segment / "ports" / Segment / RemainingPath) {
      (workflow, instance, port, path) ⇒ handle(instanceProxy(workflow, instance, port, path))
    } ~ path(Deployment.kind / Segment / "clusters" / Segment / "services" / Segment / "instances" / Segment / "ports" / Segment / RemainingPath) {
      (deployment, cluster, service, instance, port, path) ⇒ handle(instanceProxy(deployment, cluster, service, instance, port, path))
    }

  private def handle(handler: (RequestContext, Option[UpgradeToWebSocket]) ⇒ Future[RouteResult]): Route = {
    extractUpgradeToWebSocket { upgrade ⇒ context ⇒ handler(context, Option(upgrade))
    } ~ {
      context ⇒ handler(context, None)
    }
  }
} 
Example 179
Source File: JobRoute.scala    From fusion-data   with Apache License 2.0 5 votes vote down vote up
package mass.job.route.api.v1

import akka.actor.ActorSystem
import akka.http.scaladsl.server.Route
import com.typesafe.scalalogging.StrictLogging
import fusion.http.server.{ AbstractRoute, JacksonDirectives }
import fusion.json.jackson.http.JacksonSupport
import javax.inject.{ Inject, Singleton }
import mass.common.page.Page
import mass.extension.MassCore
import mass.job.service.job.JobService
import mass.message.job._

@Singleton
class JobRoute @Inject() (jobService: JobService, val jacksonSupport: JacksonSupport)(implicit system: ActorSystem)
    extends AbstractRoute
    with JacksonDirectives
    with StrictLogging {
  private val pagePDM = ('page.as[Int].?(Page.DEFAULT_PAGE), Symbol("size").as[Int].?(Page.DEFAULT_SIZE), 'key.?)

  override def route: Route = pathPrefix("job") {
    createJobRoute ~
    updateJobRoute ~
    pageRoute ~
    itemByKeyRoute ~
    uploadJobZipRoute ~
    optionAllRoute ~
    uploadFileRoute
  }

  def createJobRoute: Route = pathPost("create") {
    entity(jacksonAs[JobCreateReq]) { req =>
      futureComplete(jobService.createJob(req))
    }
  }

  def updateJobRoute: Route = pathPost("update") {
    entity(jacksonAs[JobUpdateReq]) { req =>
      futureComplete(jobService.updateJob(req))
    }
  }

  def itemByKeyRoute: Route = pathGet("item" / Segment) { key =>
    futureComplete(jobService.findItemByKey(key))
  }

  def pageRoute: Route = pathGet("page") {
    parameters(pagePDM).as(JobPageReq.apply _) { req =>
      futureComplete(jobService.page(req))
    }
  }

  def uploadJobZipRoute: Route = pathPost("upload_job") {
    extractExecutionContext { implicit ec =>
      storeUploadedFile("job", createTempFileFunc(MassCore(system).tempDirectory)) {
        case (fileInfo, file) =>
          futureComplete(jobService.uploadJobOnZip(fileInfo, file.toPath))
      }
    }
  }

  def uploadFileRoute: Route = pathPost("upload_file") {
    extractExecutionContext { implicit ec =>
      uploadedFiles(createTempFileFunc(MassCore(system).tempDirectory)) { list =>
        futureComplete(jobService.uploadFiles(list))
      }
    }
  }

  def optionAllRoute: Route = pathGet("option_all") {
    futureComplete(jobService.listOption())
  }
} 
Example 180
Source File: MockRoute.scala    From fusion-data   with Apache License 2.0 5 votes vote down vote up
package mass.job.route.api

import akka.http.scaladsl.server.Route
import fusion.http.server.AbstractRoute
import fusion.json.jackson.http.JacksonSupport
import javax.inject.{ Inject, Singleton }

@Singleton
class MockRoute @Inject() (val jacksonSupport: JacksonSupport) extends AbstractRoute {
  override def route: Route = pathPrefix("api") {
    currentUser ~ ruleRoute
  }

  def ruleRoute: Route = pathGet("rule") {
    objectComplete(jacksonSupport.objectMapper.createArrayNode)
  }

  def currentUser: Route = pathGet("currentUser") {
    objectComplete(jacksonSupport.objectMapper.readTree(Mock.currentUser))
  }
}

object Mock {
  val currentUser =
    """{"name":"Serati Ma","avatar":"https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png","userid":"00000001","email":"[email protected]","signature":"海纳百川,有容乃大","title":"交互专家","group":"蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED","tags":[{"key":"0","label":"很有想法的"},{"key":"1","label":"专注设计"},{"key":"2","label":"辣~"},{"key":"3","label":"大长腿"},{"key":"4","label":"川妹子"},{"key":"5","label":"海纳百川"}],"notifyCount":12,"country":"China","geographic":{"province":{"label":"浙江省","key":"330000"},"city":{"label":"杭州市","key":"330100"}},"address":"西湖区工专路 77 号","phone":"0752-268888888"}"""
} 
Example 181
Source File: Api.scala    From streamee   with Apache License 2.0 5 votes vote down vote up
package io.moia.streamee.demo

import akka.Done
import akka.actor.{ CoordinatedShutdown, ActorSystem => ClassicSystem }
import akka.actor.CoordinatedShutdown.{ PhaseServiceUnbind, Reason }
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes.{ BadRequest, InternalServerError, OK }
import akka.http.scaladsl.server.Route
import io.moia.streamee.FrontProcessor
import org.slf4j.LoggerFactory
import scala.concurrent.duration.FiniteDuration
import scala.util.{ Failure, Success }

object Api {

  type TextShufflerProcessor =
    FrontProcessor[TextShuffler.ShuffleText, Either[TextShuffler.Error, TextShuffler.TextShuffled]]

  final case class Config(interface: String, port: Int, terminationDeadline: FiniteDuration)

  private final object BindFailure extends Reason

  private val logger = LoggerFactory.getLogger(getClass)

  def apply(config: Config, textShufflerProcessor: TextShufflerProcessor)(implicit
      classicSystem: ClassicSystem
  ): Unit = {
    import FrontProcessor.processorUnavailableHandler
    import classicSystem.dispatcher
    import config._

    val shutdown = CoordinatedShutdown(classicSystem)

    Http()
      .bindAndHandle(route(textShufflerProcessor), interface, port)
      .onComplete {
        case Failure(cause) =>
          if (logger.isErrorEnabled)
            logger.error(s"Shutting down, because cannot bind to $interface:$port!", cause)
          shutdown.run(BindFailure)

        case Success(binding) =>
          if (logger.isInfoEnabled)
            logger.info(s"Listening for HTTP connections on ${binding.localAddress}")
          shutdown.addTask(PhaseServiceUnbind, "api.unbind") { () =>
            binding.terminate(terminationDeadline).map(_ => Done)
          }
      }
  }

  def route(textShufflerProcessor: TextShufflerProcessor): Route = {
    import akka.http.scaladsl.server.Directives._
    import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
    import io.circe.generic.auto._

    pathSingleSlash {
      get {
        complete {
          OK
        }
      }
    } ~
    path("shuffle") {
      import TextShuffler._
      post {
        entity(as[ShuffleText]) { shuffleText =>
          onSuccess(textShufflerProcessor.offer(shuffleText)) {
            case Left(Error.EmptyText)                 => complete(BadRequest -> "Empty text!")
            case Left(Error.InvalidText)               => complete(BadRequest -> "Invalid text!")
            case Left(Error.RandomError)               => complete(InternalServerError -> "Random error!")
            case Left(Error.EmptyWordSeq)              => complete(InternalServerError -> "Words empty!")
            case Right(TextShuffled(original, result)) => complete(s"$original -> $result")
          }
        }
      }
    }
  }
} 
Example 182
Source File: ServerVersionRoute.scala    From learn-akka   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.learn.akka.http.routes

import akka.http.scaladsl.model.{ContentTypes, HttpEntity}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.allaboutscala.learn.akka.http.jsonsupport.{JsonSupport, AkkaHttpRestServer}


class ServerVersion extends JsonSupport {

  def route(): Route = {
    path("server-version") {
      get {
        val serverVersion = "1.0.0.0"
        complete(HttpEntity(ContentTypes.`text/plain(UTF-8)`, serverVersion))
      }
    }
  }



  def routeAsJson(): Route = {
    path("server-version-json") {
      get {
        val jsonResponse =
          """
            |{
            | "app": "Akka HTTP REST Server",
            | "version": "1.0.0.0"
            |}
          """.stripMargin
        complete(HttpEntity(ContentTypes.`application/json`, jsonResponse))
      }
    }
  }



  def routeAsJsonEncoding(): Route = {
    path("server-version-json-encoding") {
      get {
        val server = AkkaHttpRestServer("Akka HTTP REST Server", "1.0.0.0")
        complete(server)
      }
    }
  }
} 
Example 183
Source File: DonutQueryParametersTest.scala    From learn-akka   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.learn.akka.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.allaboutscala.learn.akka.http.routes.DonutRoutes
import org.scalatest.{Matchers, WordSpec}


class DonutQueryParametersTest
  extends WordSpec
    with Matchers
    with ScalatestRouteTest {

  val donutRoutes = new DonutRoutes().route()

  "Query Parameters Tests" should {
    "match the output for the URL /donut/prices?donutName" in {
      Get("/donut/prices?donutName=plain%20donut") ~> donutRoutes ~> check {
        responseAs[String] shouldEqual "Received parameter: donutName=plain donut"
        status shouldEqual StatusCodes.OK
      }
    }



    "Check for required donutName query parameter at /donut/prices" in {
      Get("/donut/prices?") ~> Route.seal(donutRoutes) ~> check {
        responseAs[String] shouldEqual "Request is missing required query parameter 'donutName'"
        status shouldEqual StatusCodes.NotFound
      }
    }



    "Validate the pass-through of required and optional parameters in /donut/bake" in {
      Get("/donut/bake?donutName=plain%20donut&topping=chocolate") ~> donutRoutes ~> check {
        responseAs[String] shouldEqual "Received parameters: donutName=plain donut and topping=chocolate"
        status shouldEqual StatusCodes.OK
      }
    }



    "Verify the optional parameter topping for /donut/bake" in {
      Get("/donut/bake?donutName=plain%20donut") ~> donutRoutes ~> check {
        responseAs[String] shouldEqual "Received parameters: donutName=plain donut and topping=sprinkles"
        status shouldEqual StatusCodes.OK
      }
    }



    "Verify typed parameters for /ingredients" in {
      Get("/ingredients?donutName=plain%20donut&priceLevel=1.50") ~> donutRoutes ~> check {
        responseAs[String] shouldEqual "Received parameters: donutName=plain donut, priceLevel=1.5"
        status shouldEqual StatusCodes.OK
      }
    }



    "Check for wrong types being passed through to the priceLevel query param at /ingredients" in {
      Get("/ingredients?donutName=plain%20donut&priceLevel=cheap") ~> Route.seal(donutRoutes) ~> check {
        responseAs[String] shouldEqual """The query parameter 'priceLevel' was malformed:
                                         |'cheap' is not a valid 64-bit floating point value""".stripMargin
        status shouldEqual StatusCodes.BadRequest
      }
    }



    "Verify CSV parameters for /bake-donuts" in {
      Get("/bake-donuts?ingredients=flour,sugar,vanilla") ~> donutRoutes ~> check {
        responseAs[String] shouldEqual "Received CSV parameter: ingredients=List(flour, sugar, vanilla)"
        status shouldEqual StatusCodes.OK
      }
    }
  }
} 
Example 184
Source File: EventRoutes.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.{Organization, Project}
import ch.epfl.bluebrain.nexus.iam.client.config.IamClientConfig
import ch.epfl.bluebrain.nexus.iam.client.types.{AccessControlLists, Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives._
import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._
import kamon.instrumentation.akka.http.TracingDirectives.operationName

class EventRoutes(acls: AccessControlLists, caller: Caller)(implicit as: ActorSystem, config: AppConfig)
    extends EventCommonRoutes {

  private val read: Permission                  = Permission.unsafe("resources/read")
  private implicit val acl: AccessControlLists  = acls
  private implicit val c: Caller                = caller
  private implicit val iamConf: IamClientConfig = config.iam.iamClient

  def routes(project: Project): Route = {
    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/resources/{org}/{project}/events") {
        implicit val p: Project = project
        hasPermission(read).apply {
          complete(source(s"project=${project.uuid}", offset))
        }
      }
    }
  }

  def routes(org: Organization): Route =
    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/resources/{org}/events") {
        hasPermission(read, org.label).apply {
          complete(source(s"org=${org.uuid}", offset))
        }
      }
    }
} 
Example 185
Source File: TagRoutes.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.Project
import ch.epfl.bluebrain.nexus.iam.client.types._
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.config.Contexts.tagCtxUri
import ch.epfl.bluebrain.nexus.kg.config.Vocabulary.nxv
import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives._
import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources._
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import io.circe.syntax._
import io.circe.{Encoder, Json}
import kamon.Kamon
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class TagRoutes private[routes] (resourceType: String, tags: Tags[Task], schema: Ref, write: Permission)(
    implicit acls: AccessControlLists,
    caller: Caller,
    project: Project,
    config: AppConfig
) {

  
  def routes(id: AbsoluteIri): Route =
    // Consume the tag segment
    pathPrefix("tags") {
      concat(
        // Create tag
        (post & parameter("rev".as[Long]) & pathEndOrSingleSlash) { rev =>
          operationName(opName) {
            (hasPermission(write) & projectNotDeprecated) {
              entity(as[Json]) { source =>
                Kamon.currentSpan().tag("resource.operation", "create")
                complete(tags.create(Id(project.ref, id), rev, source, schema).value.runWithStatus(Created))
              }
            }
          }
        },
        // Fetch a tag
        (get & projectNotDeprecated & pathEndOrSingleSlash) {
          operationName(opName) {
            hasPermission(read).apply {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(tags.fetch(Id(project.ref, id), rev, schema).value.runWithStatus(OK))
                case _         => complete(tags.fetch(Id(project.ref, id), schema).value.runWithStatus(OK))
              }
            }
          }
        }
      )
    }

  private implicit def tagsEncoder: Encoder[TagSet] =
    Encoder.instance(tags => Json.obj(nxv.tags.prefix -> Json.arr(tags.map(_.asJson).toSeq: _*)).addContext(tagCtxUri))

  private def opName: String = resourceType match {
    case "resources" => s"/${config.http.prefix}/resources/{org}/{project}/{schemaId}/{id}/tags"
    case _           => s"/${config.http.prefix}/$resourceType/{org}/{project}/{id}/tags"
  }
} 
Example 186
Source File: ArchiveRoutes.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.http.scaladsl.model.StatusCodes.{Created, OK}
import akka.http.scaladsl.model.headers.Accept
import akka.http.scaladsl.model.{HttpEntity, MediaTypes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.admin.client.types.Project
import ch.epfl.bluebrain.nexus.iam.client.types._
import ch.epfl.bluebrain.nexus.kg.KgError.{InvalidOutputFormat, UnacceptedResponseContentType}
import ch.epfl.bluebrain.nexus.kg.archives.Archive._
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives.hasPermission
import ch.epfl.bluebrain.nexus.kg.directives.PathDirectives._
import ch.epfl.bluebrain.nexus.kg.directives.ProjectDirectives._
import ch.epfl.bluebrain.nexus.kg.directives.QueryDirectives.outputFormat
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources._
import ch.epfl.bluebrain.nexus.kg.resources.syntax._
import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.Tar
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import io.circe.Json
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

class ArchiveRoutes private[routes] (archives: Archives[Task])(
    implicit acls: AccessControlLists,
    project: Project,
    caller: Caller,
    config: AppConfig
) {

  private val responseType = MediaTypes.`application/x-tar`

  
  def routes(id: AbsoluteIri): Route = {
    val resId = Id(project.ref, id)
    concat(
      // Create archive
      (put & pathEndOrSingleSlash) {
        operationName(s"/${config.http.prefix}/archives/{org}/{project}/{id}") {
          (hasPermission(write) & projectNotDeprecated) {
            entity(as[Json]) { source =>
              complete(archives.create(resId, source).value.runWithStatus(Created))
            }
          }
        }
      },
      // Fetch archive
      (get & outputFormat(strict = true, Tar) & pathEndOrSingleSlash) {
        case Tar                           => getArchive(resId)
        case format: NonBinaryOutputFormat => getResource(resId)(format)
        case other                         => failWith(InvalidOutputFormat(other.toString))

      }
    )
  }

  private def getResource(resId: ResId)(implicit format: NonBinaryOutputFormat): Route =
    completeWithFormat(archives.fetch(resId).value.runWithStatus(OK))

  private def getArchive(resId: ResId): Route = {
    parameter("ignoreNotFound".as[Boolean] ? false) { ignoreNotFound =>
      onSuccess(archives.fetchArchive(resId, ignoreNotFound).value.runToFuture) {
        case Right(source) =>
          headerValueByType[Accept](()) { accept =>
            if (accept.mediaRanges.exists(_.matches(responseType)))
              complete(HttpEntity(responseType, source))
            else
              failWith(
                UnacceptedResponseContentType(
                  s"File Media Type '$responseType' does not match the Accept header value '${accept.mediaRanges.mkString(", ")}'"
                )
              )
          }
        case Left(err) => complete(err)
      }
    }
  }
}

object ArchiveRoutes {
  final def apply(archives: Archives[Task])(
      implicit acls: AccessControlLists,
      caller: Caller,
      project: Project,
      config: AppConfig
  ): ArchiveRoutes = new ArchiveRoutes(archives)
} 
Example 187
Source File: GlobalEventRoutes.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling.sse.EventStreamMarshalling._
import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.client.config.IamClientConfig
import ch.epfl.bluebrain.nexus.iam.client.types.{AccessControlLists, Caller, Permission}
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.directives.AuthDirectives._
import ch.epfl.bluebrain.nexus.kg.persistence.TaggingAdapter
import ch.epfl.bluebrain.nexus.kg.resources.Event.JsonLd._
import kamon.instrumentation.akka.http.TracingDirectives.operationName

class GlobalEventRoutes(acls: AccessControlLists, caller: Caller)(implicit as: ActorSystem, config: AppConfig)
    extends EventCommonRoutes {

  private val read: Permission                  = Permission.unsafe("events/read")
  private implicit val acl: AccessControlLists  = acls
  private implicit val c: Caller                = caller
  private implicit val iamConf: IamClientConfig = config.iam.iamClient

  def routes: Route =
    lastEventId { offset =>
      operationName(s"/${config.http.prefix}/events") {
        hasPermissionOnRoot(read).apply {
          complete(source(TaggingAdapter.EventTag, offset))
        }
      }
    }
} 
Example 188
Source File: package.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg

import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.server.Directives.complete
import akka.http.scaladsl.server.{MalformedQueryParamRejection, Route}
import cats.Functor
import cats.data.{EitherT, OptionT}
import cats.instances.future._
import ch.epfl.bluebrain.nexus.iam.client.types._
import ch.epfl.bluebrain.nexus.kg.marshallers.instances._
import ch.epfl.bluebrain.nexus.kg.resources.Rejection.NotFound.notFound
import ch.epfl.bluebrain.nexus.kg.resources.{Ref, Rejection, ResourceV}
import ch.epfl.bluebrain.nexus.kg.routes.OutputFormat.{DOT, Triples}
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import monix.execution.Scheduler.Implicits.global

import scala.concurrent.Future

package object routes {

  private[routes] def completeWithFormat(
      fetched: Future[Either[Rejection, (StatusCode, ResourceV)]]
  )(implicit format: NonBinaryOutputFormat): Route =
    completeWithFormat(EitherT(fetched))

  private def completeWithFormat(
      fetched: EitherT[Future, Rejection, (StatusCode, ResourceV)]
  )(implicit format: NonBinaryOutputFormat): Route =
    format match {
      case f: JsonLDOutputFormat =>
        implicit val format = f
        complete(fetched.value)
      case Triples =>
        implicit val format = Triples
        complete(fetched.map { case (status, resource) => status -> resource.value.graph.ntriples }.value)
      case DOT =>
        implicit val format = DOT
        complete(fetched.map { case (status, resource) => status -> resource.value.graph.dot() }.value)
    }

  private[routes] val read: Permission = Permission.unsafe("resources/read")

  private[routes] val schemaError =
    MalformedQueryParamRejection("schema", "The provided schema does not match the schema on the Uri")

  private[routes] implicit class FOptionSyntax[F[_], A](private val fOpt: F[Option[A]]) extends AnyVal {
    def toNotFound(id: AbsoluteIri)(implicit F: Functor[F]): EitherT[F, Rejection, A] =
      OptionT(fOpt).toRight(notFound(Ref(id)))
  }
} 
Example 189
Source File: AliasApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.api.http.alias

import akka.NotUsed
import akka.http.scaladsl.common.{EntityStreamingSupport, JsonEntityStreamingSupport}
import akka.http.scaladsl.server.Route
import akka.stream.scaladsl.Source
import cats.syntax.either._
import com.wavesplatform.account.Alias
import com.wavesplatform.api.common.CommonTransactionsApi
import com.wavesplatform.api.http._
import com.wavesplatform.api.http.requests.CreateAliasRequest
import com.wavesplatform.http.BroadcastRoute
import com.wavesplatform.network.UtxPoolSynchronizer
import com.wavesplatform.settings.RestAPISettings
import com.wavesplatform.state.Blockchain
import com.wavesplatform.transaction._
import com.wavesplatform.utils.Time
import com.wavesplatform.wallet.Wallet
import play.api.libs.json.{JsString, JsValue, Json}

case class AliasApiRoute(
    settings: RestAPISettings,
    commonApi: CommonTransactionsApi,
    wallet: Wallet,
    utxPoolSynchronizer: UtxPoolSynchronizer,
    time: Time,
    blockchain: Blockchain
) extends ApiRoute
    with BroadcastRoute
    with AuthRoute {

  override val route: Route = pathPrefix("alias") {
    addressOfAlias ~ aliasOfAddress ~ deprecatedRoute
  }

  private def deprecatedRoute: Route =
    path("broadcast" / "create") {
      broadcast[CreateAliasRequest](_.toTx)
    } ~ (path("create") & withAuth) {
      broadcast[CreateAliasRequest](TransactionFactory.createAlias(_, wallet, time))
    }

  def addressOfAlias: Route = (get & path("by-alias" / Segment)) { aliasName =>
    complete {
      Alias
        .create(aliasName)
        .flatMap { a =>
          blockchain.resolveAlias(a).bimap(_ => TxValidationError.AliasDoesNotExist(a), addr => Json.obj("address" -> addr.stringRepr))
        }
    }
  }

  private implicit val ess: JsonEntityStreamingSupport = EntityStreamingSupport.json()

  def aliasOfAddress: Route = (get & path("by-address" / AddrSegment)) { address =>
    extractScheduler { implicit s =>
      val value: Source[JsValue, NotUsed] =
        Source.fromPublisher(commonApi.aliasesOfAddress(address).map { case (_, tx) => JsString(tx.alias.stringRepr) }.toReactivePublisher)
      complete(value)
    }
  }
} 
Example 190
Source File: RewardApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.api.http

import akka.http.scaladsl.server.Route
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.state.Blockchain
import com.wavesplatform.transaction.TxValidationError.GenericError
import play.api.libs.json.{Format, Json}

case class RewardApiRoute(blockchain: Blockchain) extends ApiRoute {
  import RewardApiRoute._

  override lazy val route: Route = pathPrefix("blockchain" / "rewards") {
    rewards ~ rewardsAtHeight()
  }

  def rewards(): Route = (get & pathEndOrSingleSlash) {
    complete(getRewards(blockchain.height))
  }

  def rewardsAtHeight(): Route = (get & path(IntNumber)) { height =>
    complete(getRewards(height))
  }

  def getRewards(height: Int): Either[ValidationError, RewardStatus] =
    for {
      _ <- Either.cond(height <= blockchain.height, (), GenericError(s"Invalid height: $height"))
      activatedAt <- blockchain
        .featureActivationHeight(BlockchainFeatures.BlockReward.id)
        .filter(_ <= height)
        .toRight(GenericError("Block reward feature is not activated yet"))
      reward <- blockchain.blockReward(height).toRight(GenericError(s"No information about rewards at height = $height"))
      amount              = blockchain.wavesAmount(height)
      settings            = blockchain.settings.rewardsSettings
      nextCheck           = settings.nearestTermEnd(activatedAt, height)
      votingIntervalStart = nextCheck - settings.votingInterval + 1
      votingThreshold     = settings.votingInterval / 2 + 1
      votes               = blockchain.blockRewardVotes(height).filter(_ >= 0)
    } yield RewardStatus(
      height,
      amount,
      reward,
      settings.minIncrement,
      settings.term,
      nextCheck,
      votingIntervalStart,
      settings.votingInterval,
      votingThreshold,
      RewardVotes(votes.count(_ > reward), votes.count(_ < reward))
    )
}

object RewardApiRoute {
  final case class RewardStatus(
      height: Int,
      totalWavesAmount: BigInt,
      currentReward: Long,
      minIncrement: Long,
      term: Int,
      nextCheck: Int,
      votingIntervalStart: Int,
      votingInterval: Int,
      votingThreshold: Int,
      votes: RewardVotes
  )

  final case class RewardVotes(increase: Int, decrease: Int)

  implicit val rewardVotesFormat: Format[RewardVotes] = Json.format
  implicit val rewardFormat: Format[RewardStatus]     = Json.format
} 
Example 191
Source File: TimeLimitedRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.api.http

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.server.{Directive1, ExceptionHandler, Route}
import com.google.common.util.concurrent.{ExecutionError, UncheckedExecutionException}
import com.wavesplatform.utils.Schedulers
import monix.execution.Scheduler

import scala.concurrent.ExecutionException

trait TimeLimitedRoute { self: ApiRoute =>
  def limitedScheduler: Scheduler

  def executeLimited[T](f: => T): Directive1[T] = {
    val handler = ExceptionHandler {
      case _: InterruptedException | _: ExecutionException | _: ExecutionError | _: UncheckedExecutionException =>
        complete(ApiError.CustomValidationError("The request took too long to complete"))
    }
    handleExceptions(handler) & onSuccess(Schedulers.executeCatchingInterruptedException(limitedScheduler)(f))
  }

  def completeLimited(f: => ToResponseMarshallable): Route =
    executeLimited(f)(complete(_))
} 
Example 192
Source File: LeaseApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.api.http.leasing

import akka.http.scaladsl.server.Route
import com.wavesplatform.api.common.CommonAccountsApi
import com.wavesplatform.api.http._
import com.wavesplatform.api.http.requests.{LeaseCancelRequest, LeaseRequest}
import com.wavesplatform.http.BroadcastRoute
import com.wavesplatform.network.UtxPoolSynchronizer
import com.wavesplatform.settings.RestAPISettings
import com.wavesplatform.state.Blockchain
import com.wavesplatform.transaction._
import com.wavesplatform.transaction.lease.LeaseTransaction
import com.wavesplatform.utils.Time
import com.wavesplatform.wallet.Wallet
import play.api.libs.json.JsNumber

case class LeaseApiRoute(
    settings: RestAPISettings,
    wallet: Wallet,
    blockchain: Blockchain,
    utxPoolSynchronizer: UtxPoolSynchronizer,
    time: Time,
    commonAccountApi: CommonAccountsApi
) extends ApiRoute
    with BroadcastRoute
    with AuthRoute {

  override val route: Route = pathPrefix("leasing") {
    active ~ deprecatedRoute
  }

  private def deprecatedRoute: Route =
    (path("lease") & withAuth) {
      broadcast[LeaseRequest](TransactionFactory.lease(_, wallet, time))
    } ~ (path("cancel") & withAuth) {
      broadcast[LeaseCancelRequest](TransactionFactory.leaseCancel(_, wallet, time))
    } ~ pathPrefix("broadcast") {
      path("lease")(broadcast[LeaseRequest](_.toTx)) ~
        path("cancel")(broadcast[LeaseCancelRequest](_.toTx))
    }

  def active: Route = (pathPrefix("active") & get & extractScheduler) { implicit sc =>
    path(AddrSegment) { address =>
      complete(
        commonAccountApi
          .activeLeases(address)
          .collect {
            case (height, leaseTransaction: LeaseTransaction) =>
              leaseTransaction.json() + ("height" -> JsNumber(height))
          }
          .toListL
          .runToFuture
      )
    }
  }
} 
Example 193
Source File: ActivationApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.features.api

import akka.http.scaladsl.server.Route
import com.wavesplatform.api.http.ApiRoute
import com.wavesplatform.features.{BlockchainFeatureStatus, BlockchainFeatures}
import com.wavesplatform.settings.{FeaturesSettings, RestAPISettings}
import com.wavesplatform.state.Blockchain
import play.api.libs.json.Json

case class ActivationApiRoute(settings: RestAPISettings, featuresSettings: FeaturesSettings, blockchain: Blockchain) extends ApiRoute {

  override lazy val route: Route = pathPrefix("activation") {
    status
  }

  def status: Route = (get & path("status")) {
    val height = blockchain.height

    val featureIds = (blockchain.featureVotes(height).keySet ++
      blockchain.approvedFeatures.keySet ++
      BlockchainFeatures.implemented).toSeq.sorted

    complete(
      Json.toJson(
        ActivationStatus(
          height,
          blockchain.settings.functionalitySettings.activationWindowSize(height),
          blockchain.settings.functionalitySettings.blocksForFeatureActivation(height),
          blockchain.settings.functionalitySettings.activationWindow(height).last,
          featureIds.map { id =>
            val status = blockchain.featureStatus(id, height)
            val voted = featuresSettings.supported.contains(id) && !blockchain.activatedFeatures
              .get(id)
              .exists(_ <= height) && !blockchain.settings.functionalitySettings.preActivatedFeatures.contains(id)

            FeatureActivationStatus(
              id,
              BlockchainFeatures.feature(id).fold("Unknown feature")(_.description),
              status,
              (BlockchainFeatures.implemented.contains(id), voted) match {
                case (false, _) => NodeFeatureStatus.NotImplemented
                case (_, true)  => NodeFeatureStatus.Voted
                case _          => NodeFeatureStatus.Implemented
              },
              blockchain.featureActivationHeight(id),
              if (status == BlockchainFeatureStatus.Undefined) blockchain.featureVotes(height).get(id).orElse(Some(0)) else None
            )
          }
        )
      )
    )
  }
} 
Example 194
Source File: NodeApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.http

import java.time.Instant

import akka.http.scaladsl.server.Route
import com.wavesplatform.Shutdownable
import com.wavesplatform.api.http.{ApiRoute, AuthRoute}
import com.wavesplatform.settings.{Constants, RestAPISettings}
import com.wavesplatform.state.Blockchain
import com.wavesplatform.utils.ScorexLogging
import play.api.libs.json.Json

case class NodeApiRoute(settings: RestAPISettings, blockchain: Blockchain, application: Shutdownable)
    extends ApiRoute
    with AuthRoute
    with ScorexLogging {

  override lazy val route: Route = pathPrefix("node") {
    stop ~ status ~ version
  }

  def version: Route = (get & path("version")) {
    complete(Json.obj("version" -> Constants.AgentName))
  }

  def stop: Route = (post & path("stop") & withAuth) {
    log.info("Request to stop application")
    application.shutdown()
    complete(Json.obj("stopped" -> true))
  }

  def status: Route = (get & path("status")) {
    val lastUpdated = blockchain.lastBlockHeader.get.header.timestamp
    complete(
      Json.obj(
        "blockchainHeight" -> blockchain.height,
        "stateHeight"      -> blockchain.height,
        "updatedTimestamp" -> lastUpdated,
        "updatedDate"      -> Instant.ofEpochMilli(lastUpdated).toString
      )
    )
  }
} 
Example 195
Source File: BroadcastRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.http

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.server.Route
import cats.syntax.either._
import com.wavesplatform.api.http.{ApiError, ApiRoute, jsonParammedPost}
import com.wavesplatform.lang.ValidationError
import com.wavesplatform.network._
import com.wavesplatform.transaction.Transaction
import play.api.libs.json._

trait BroadcastRoute { _: ApiRoute =>
  def utxPoolSynchronizer: UtxPoolSynchronizer

  def broadcast[A: Reads](f: A => Either[ValidationError, Transaction]): Route = jsonParammedPost[A] { (a, params) =>
    f(a).fold[ToResponseMarshallable](
      ApiError.fromValidationError,
      tx => {
        val p = utxPoolSynchronizer.publish(tx)
        p.transformE(r => r.bimap(ApiError.fromValidationError, t => tx.json() ++ params.get("trace").fold(Json.obj())(_ => Json.obj("trace" -> p.trace.map(_.loggedJson)))))
      }
    )
  }
} 
Example 196
Source File: NxtConsensusApiRoute.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.consensus.nxt.api.http

import akka.http.scaladsl.server.Route
import com.wavesplatform.api.http.ApiError.BlockDoesNotExist
import com.wavesplatform.api.http._
import com.wavesplatform.block.BlockHeader
import com.wavesplatform.common.state.ByteStr
import com.wavesplatform.features.BlockchainFeatures
import com.wavesplatform.settings.RestAPISettings
import com.wavesplatform.state.Blockchain
import play.api.libs.json.{JsObject, Json}


case class NxtConsensusApiRoute(settings: RestAPISettings, blockchain: Blockchain) extends ApiRoute {

  override val route: Route =
    pathPrefix("consensus") {
      algo ~ basetarget ~ baseTargetId ~ generatingBalance
    }

  def generatingBalance: Route = (path("generatingbalance" / AddrSegment) & get) { address =>
    complete(Json.obj("address" -> address.stringRepr, "balance" -> blockchain.generatingBalance(address)))
  }

  private def headerForId(blockId: ByteStr, f: BlockHeader => JsObject) =
    complete {
      (for {
        height <- blockchain.heightOf(blockId)
        meta   <- blockchain.blockHeader(height)
      } yield f(meta.header)).toRight[ApiError](BlockDoesNotExist)
    }

  def baseTargetId: Route = (path("basetarget" / Signature) & get) { signature =>
    headerForId(signature, m => Json.obj("baseTarget" -> m.baseTarget))
  }

  def basetarget: Route = (path("basetarget") & get) {
    complete(
      blockchain.lastBlockHeader
        .map(m => Json.obj("baseTarget" -> m.header.baseTarget))
        .toRight(BlockDoesNotExist)
    )
  }

  def algo: Route = (path("algo") & get) {
    complete(
      if (blockchain.activatedFeatures.contains(BlockchainFeatures.FairPoS.id))
        Json.obj("consensusAlgo" -> "Fair Proof-of-Stake (FairPoS)")
      else
        Json.obj("consensusAlgo" -> "proof-of-stake (PoS)")
    )
  }
} 
Example 197
Source File: AssetsRouteSpec.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import com.wavesplatform.account.Address
import com.wavesplatform.api.common.{CommonAccountsApi, CommonAssetsApi}
import com.wavesplatform.api.http.assets.AssetsApiRoute
import com.wavesplatform.api.http.requests.{TransferV1Request, TransferV2Request}
import com.wavesplatform.http.ApiMarshallers._
import com.wavesplatform.state.Blockchain
import com.wavesplatform.transaction.transfer._
import com.wavesplatform.wallet.Wallet
import com.wavesplatform.{RequestGen, TestTime}
import org.scalamock.scalatest.PathMockFactory
import org.scalatest.concurrent.Eventually
import play.api.libs.json.Writes

class AssetsRouteSpec extends RouteSpec("/assets") with RequestGen with PathMockFactory with Eventually with RestAPISettingsHelper {

  private val wallet = stub[Wallet]
  private val state  = stub[Blockchain]

  private val seed               = "seed".getBytes("UTF-8")
  private val senderPrivateKey   = Wallet.generateNewAccount(seed, 0)
  private val receiverPrivateKey = Wallet.generateNewAccount(seed, 1)

  (wallet.privateKeyAccount _).when(senderPrivateKey.toAddress).onCall((_: Address) => Right(senderPrivateKey)).anyNumberOfTimes()

  "/transfer" - {
    val route: Route = AssetsApiRoute(
      restAPISettings,
      wallet,
      DummyUtxPoolSynchronizer.accepting,
      state,
      new TestTime(),
      mock[CommonAccountsApi],
      mock[CommonAssetsApi]
    ).route

    def posting[A: Writes](v: A): RouteTestResult = Post(routePath("/transfer"), v).addHeader(ApiKeyHeader) ~> route

    "accepts TransferRequest" in {
      val req = TransferV1Request(
        assetId = None,
        feeAssetId = None,
        amount = 1 * Waves,
        fee = Waves / 3,
        sender = senderPrivateKey.toAddress.toString,
        attachment = Some("attachment"),
        recipient = receiverPrivateKey.toAddress.toString,
        timestamp = Some(System.currentTimeMillis())
      )

      posting(req) ~> check {
        status shouldBe StatusCodes.OK

        responseAs[TransferTransaction]
      }
    }

    "accepts VersionedTransferRequest" in {
      val req = TransferV2Request(
        assetId = None,
        amount = 1 * Waves,
        feeAssetId = None,
        fee = Waves / 3,
        sender = senderPrivateKey.toAddress.toString,
        attachment = None,
        recipient = receiverPrivateKey.toAddress.toString,
        timestamp = Some(System.currentTimeMillis())
      )

      posting(req) ~> check {
        status shouldBe StatusCodes.OK
        responseAs[TransferV2Request]
      }
    }

    "returns a error if it is not a transfer request" in {
      val req = issueReq.sample.get
      posting(req) ~> check {
        status shouldNot be(StatusCodes.OK)
      }
    }
  }

} 
Example 198
Source File: ConsensusRouteSpec.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.http

import akka.http.scaladsl.server.Route
import com.wavesplatform.BlockGen
import com.wavesplatform.api.http.ApiError.BlockDoesNotExist
import com.wavesplatform.consensus.nxt.api.http.NxtConsensusApiRoute
import com.wavesplatform.db.WithDomain
import com.wavesplatform.http.ApiMarshallers._
import com.wavesplatform.state._
import org.scalatestplus.scalacheck.{ScalaCheckPropertyChecks => PropertyChecks}
import play.api.libs.json.JsObject

class ConsensusRouteSpec
    extends RouteSpec("/consensus")
    with RestAPISettingsHelper
    with PropertyChecks
    with BlockGen
    with HistoryTest
    with WithDomain {

  private def routeTest(f: (Blockchain, Route) => Any) = withDomain() { d =>
    d.blockchainUpdater.processBlock(genesisBlock, genesisBlock.header.generationSignature)
    1 to 10 foreach { _ =>
      val block = getNextTestBlock(d.blockchainUpdater)
      d.blockchainUpdater.processBlock(block, block.header.generationSignature)
    }
    f(d.blockchainUpdater, NxtConsensusApiRoute(restAPISettings, d.blockchainUpdater).route)
  }

  routePath("/basetarget") - {
    "for existing block" in routeTest { (h, route) =>
      val sh = h.blockHeader(3).get
      Get(routePath(s"/basetarget/${sh.id()}")) ~> route ~> check {
        (responseAs[JsObject] \ "baseTarget").as[Long] shouldEqual sh.header.baseTarget
      }
    }

    "for non-existent block" in routeTest { (h, route) =>
      Get(routePath(s"/basetarget/24aTK4mg6DMFKw4SuQCfSRG52MXg8DSjDWQopahs38Cm3tPMFM1m6fGqCoPY69kstM7TE4mpJAMYmG7LWTTjndCH")) ~> route should produce(BlockDoesNotExist)
    }
  }
} 
Example 199
Source File: AuthenticationRouter.scala    From akka-http-rest-api   with MIT License 5 votes vote down vote up
package authentication

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import core.{StatusWrapper, ErrorWrapper, BaseRoute}
import akka.http.scaladsl.model.StatusCodes

trait AuthenticationRouter extends BaseRoute {

  import UserAuthJsonProtocol._
  import core.CommonJsonProtocol._

  def userAuthService: UserAuthService

  val authenticationRoutes: Route = {
    pathPrefix("auth") {
      (path("register") & pathEnd & post & entity(as[UserRegistrationRequest])) { request =>
        complete {
          userAuthService.register(request).map[ToResponseMarshallable] {
            case UserAuthResult.InvalidData(msg) => StatusCodes.BadRequest -> ErrorWrapper("invalidData", msg)
            case UserAuthResult.UserExists(msg) => StatusCodes.Conflict -> ErrorWrapper("userExists", msg)
            case UserAuthResult.Success(token) => StatusCodes.Created -> StatusWrapper("OK", Some(token))
          }
        }
      } ~ (path("login") & pathEnd & post & entity(as[UserLoginRequest])) { request =>
        complete {
          userAuthService.login(request).map[ToResponseMarshallable] {
            case UserAuthResult.InvalidData(msg) => StatusCodes.BadRequest -> ErrorWrapper("invalidData", msg)
            case UserAuthResult.UserNotExists(msg) => StatusCodes.BadRequest -> ErrorWrapper("userNotExists", msg)
            case UserAuthResult.Success(token) => StatusCodes.OK -> StatusWrapper("OK", Some(token))
          }
        }
      }
    }
  }
} 
Example 200
Source File: UserRouter.scala    From akka-http-rest-api   with MIT License 5 votes vote down vote up
package user

import akka.http.scaladsl.marshalling.ToResponseMarshallable
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import core.authorization.{WithPermissionRejections, Permission}
import core.{ErrorWrapper, StatusWrapper, BaseRoute}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import core.authentication.{Identity, TokenAuthenticator}

trait UserRouter extends TokenAuthenticator with Permission with WithPermissionRejections with BaseRoute {

  import UserJsonProtocol._
  import core.CommonJsonProtocol._

  def userService: UserService

  val userRoutes: Route = {
    pathPrefix("users") {
      authenticate(executor, redis) { identity =>
        (path("me") & pathEnd & get) {
          complete {
            userService.getUser(identity.user.id).map[ToResponseMarshallable] {
              case Left(msg) => StatusCodes.NotFound -> ErrorWrapper("invalidData", msg)
              case Right(user) => StatusCodes.OK -> user
            }
          }
        } ~ (path("me") & pathEnd & put & entity(as[UserUpdateRequest])) { request =>
          complete {
            userService.updateLoggedUser(identity, request).map[ToResponseMarshallable] { _ =>
              StatusCodes.OK -> StatusWrapper()
            }
          }
        } ~ (pathEnd & get & parameters('offset.as[Long], 'limit.as[Int] ? 20)) { (offset, limit) =>
          complete {
            userService.getUsers(offset, limit).map[ToResponseMarshallable] { usersResponse =>
              StatusCodes.OK -> usersResponse
            }
          }
        } ~ (path(LongNumber) & pathEnd & get) { id =>
          complete {
            userService.getUser(id).map[ToResponseMarshallable] {
              case Left(msg) => StatusCodes.NotFound -> ErrorWrapper("invalidData", msg)
              case Right(user) => StatusCodes.OK -> user
            }
          }
        } ~ (path(LongNumber) & pathEnd & delete & handleRejections(permissionRejectionHandlers) & authorize(hasPermission(identity))) { id =>
          complete {
            userService.deleteUser(id).map[ToResponseMarshallable] {
              case Left(msg) => StatusCodes.NotFound -> ErrorWrapper("invalidData", msg)
              case Right(_) => StatusCodes.OK -> StatusWrapper()
            }
          }
        } ~ (path(LongNumber / "role") & pathEnd & patch & handleRejections(permissionRejectionHandlers) & authorize(hasPermission(identity)) & entity(as[UserRoleUpdateRequest])) {
          (id, request) =>
            complete {
              userService.updateRole(id, identity, request).map[ToResponseMarshallable] {
                case Left(msg) => StatusCodes.NotFound -> ErrorWrapper("invalidData", msg)
                case Right(_) => StatusCodes.OK -> StatusWrapper()
              }
            }
        }
      }
    }
  }

  def hasPermission(identity: Identity): () => Boolean = () => identity.user.role == 1
}