akka.http.scaladsl.model.StatusCodes Scala Examples

The following examples show how to use akka.http.scaladsl.model.StatusCodes. 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: StatsApiSuite.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.iep.lwc

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.RouteTestTimeout
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.netflix.atlas.akka.RequestHandler
import com.netflix.atlas.core.model.Datapoint
import com.netflix.atlas.json.Json
import com.netflix.spectator.atlas.impl.Subscription
import com.typesafe.config.ConfigFactory
import org.scalatest.BeforeAndAfter
import org.scalatest.funsuite.AnyFunSuite

class StatsApiSuite extends AnyFunSuite with ScalatestRouteTest with BeforeAndAfter {

  import scala.jdk.CollectionConverters._
  import scala.concurrent.duration._

  private implicit val routeTestTimeout = RouteTestTimeout(5.second)

  private val config = ConfigFactory.load()
  private val evaluator = new ExpressionsEvaluator(config)
  private val endpoint = new StatsApi(evaluator)
  private val routes = RequestHandler.standardOptions(endpoint.routes)

  private def assertJsonContentType(response: HttpResponse): Unit = {
    assert(response.entity.contentType.mediaType === MediaTypes.`application/json`)
  }

  private def assertResponse(response: HttpResponse, expected: StatusCode): Unit = {
    assert(response.status === expected)
    assertJsonContentType(response)
  }

  before {
    evaluator.clear()
  }

  test("empty") {
    Get("/api/v1/stats") ~> routes ~> check {
      assertResponse(response, StatusCodes.OK)
      assert(responseAs[String] === "[]")
    }
  }

  test("has data") {
    // Add sample subscription
    val subs = List(
      new Subscription()
        .withId("1")
        .withExpression("name,ssCpuUser,:eq,:sum"),
      new Subscription()
        .withId("2")
        .withExpression("name,ssCpuSystem,:eq,:sum")
    )
    evaluator.sync(subs.asJava)

    // Stats only get updated when data is sent
    val datapoints = List(
      Datapoint(Map("name" -> "ssCpuUser", "node" -> "i-1"), 60000, 42.0),
      Datapoint(Map("name" -> "ssCpuUser", "node" -> "i-2"), 60000, 44.0)
    )
    evaluator.eval(60000, datapoints)

    // Query the data
    Get("/api/v1/stats") ~> routes ~> check {
      assertResponse(response, StatusCodes.OK)
      val stats = Json.decode[List[ExpressionsEvaluator.SubscriptionStats]](responseAs[String])
      assert(stats.length === 1)
      assert(stats.head.updateCount.get() === 2)
    }
  }
} 
Example 2
Source File: JobRouteTest.scala    From fusion-data   with Apache License 2.0 5 votes vote down vote up
package mass.job.route.api.v1

import akka.http.scaladsl.model.StatusCodes
import mass.job.SchedulerTestkit
import mass.message.job.JobPageResp

class JobRouteTest extends SchedulerTestkit {
  private lazy val route = application.instance[JobRoute].route

  "JobRoute" should {
    "page" in {
      import jacksonSupport._
      Get("/job/page") ~> route ~> check {
        status shouldBe StatusCodes.OK
        val resp = responseAs[JobPageResp]
        println(resp)
        resp should not be null
      }
    }
  }
} 
Example 3
Source File: AkkaHttpServer.scala    From learn-akka   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.learn.akka.http

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.stream.ActorMaterializer
import com.allaboutscala.learn.akka.http.routes.{DonutRoutes, ServerVersion}
import com.typesafe.scalalogging.LazyLogging

import scala.io.StdIn
import scala.util.{Failure, Success}


object AkkaHttpServer extends App with LazyLogging {

  implicit val system = ActorSystem("akka-http-rest-server")
  implicit val materializer = ActorMaterializer()
  implicit val ec = system.dispatcher

  // these should ideally be in some configuration file
  val host = "127.0.0.1"
  val port = 8080

  implicit val globalRejectionHandler =
    RejectionHandler.newBuilder()
      .handle { case ValidationRejection(msg, route) =>
        complete(StatusCodes.InternalServerError, s"The operation is not supported, error = $msg")
      }
      .handleNotFound {
        complete(StatusCodes.NotFound, "The path is not supported.")
      }
      .result()


  implicit val globalExceptionHandler = ExceptionHandler {
    case e: RuntimeException => complete(s"A runtime exception occurred with, msg = ${e.getMessage}")
  }


//  // routes
//  val serverUpRoute: Route = get {
//    complete("Akka HTTP Server is UP.")
//  }

  val serverVersion = new ServerVersion()
  val serverVersionRoute = serverVersion.route()
  val serverVersionRouteAsJson = serverVersion.routeAsJson()
  val serverVersionJsonEncoding = serverVersion.routeAsJsonEncoding()
  val donutRoutes = new DonutRoutes().route()

  val routes: Route =  donutRoutes ~ serverVersionRoute ~ serverVersionRouteAsJson ~ serverVersionJsonEncoding//
  // ~ serverUpRoute

  val httpServerFuture = Http().bindAndHandle(routes, host, port)
  httpServerFuture.onComplete {
    case Success(binding) =>
      logger.info(s"Akka Http Server is UP and is bound to ${binding.localAddress}")

    case Failure(e) =>
      logger.error(s"Akka Http server failed to start", e)
      system.terminate()
  }

  StdIn.readLine() // let it run until user presses return
  httpServerFuture
    .flatMap(_.unbind()) // trigger unbinding from the port
    .onComplete(_ => system.terminate()) // and shutdown when done
} 
Example 4
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 5
Source File: EventRoutesSpec.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.client.types._
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.resources.Event
import ch.epfl.bluebrain.nexus.kg.routes.EventRoutesSpec.TestableEventRoutes
import io.circe.Encoder

class EventRoutesSpec extends EventsSpecBase {

  val eventRoutes = new TestableEventRoutes(events, acls, caller)

  "EventRoutes" should {

    "return all events for a project" in {
      Get("/") ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }

    "return all events for an organization" in {
      Get("/") ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for an organization from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }

}

object EventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: AccessControlLists, caller: Caller)(
      implicit as: ActorSystem,
      config: AppConfig
  ) extends EventRoutes(acls, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 6
Source File: GlobalEventRoutesSpec.scala    From nexus-kg   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
import ch.epfl.bluebrain.nexus.iam.client.types.{AccessControlLists, Caller}
import ch.epfl.bluebrain.nexus.kg.config.AppConfig
import ch.epfl.bluebrain.nexus.kg.resources.Event
import ch.epfl.bluebrain.nexus.kg.routes.GlobalEventRoutesSpec.TestableEventRoutes
import io.circe.Encoder

class GlobalEventRoutesSpec extends EventsSpecBase {

  val routes = new TestableEventRoutes(events, acls, caller).routes

  "GlobalEventRoutes" should {

    "return all events for a project" in {
      Get("/") ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }
}

object GlobalEventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: AccessControlLists, caller: Caller)(
      implicit as: ActorSystem,
      config: AppConfig
  ) extends GlobalEventRoutes(acls, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 7
Source File: InvokeFailFreeSuite.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.it.sync.smartcontract

import akka.http.scaladsl.model.StatusCodes
import com.wavesplatform.common.utils.EitherExt2
import com.wavesplatform.it.api.SyncHttpApi._
import com.wavesplatform.it.api.TransactionInfo
import com.wavesplatform.it.sync.setScriptFee
import com.wavesplatform.it.transactions.BaseTransactionSuite
import com.wavesplatform.lang.v1.compiler.Terms.CONST_BOOLEAN
import com.wavesplatform.lang.v1.estimator.v3.ScriptEstimatorV3
import com.wavesplatform.transaction.smart.script.ScriptCompiler

class InvokeFailFreeSuite extends BaseTransactionSuite {
  private val dApp = firstAddress

  protected override def beforeAll(): Unit = {
    super.beforeAll()
    val script =
      compile(
        s"""
          | {-# STDLIB_VERSION 4 #-}
          | {-# CONTENT_TYPE DAPP #-}
          |
          | @Callable(inv)
          | func default(reject: Boolean) = {
          |   let check =
          |     if (reject)
          |       then
          |         ${"sigVerify(base58'', base58'', base58'') ||" * 7} true
          |       else
          |         ${"sigVerify(base58'', base58'', base58'') ||" * 8} false
          |
          |   if (check)
          |     then throw("rejected")
          |     else throw("failed")
          | }
        """.stripMargin
      )

    val setScriptId = sender.setScript(dApp, Some(script), setScriptFee, waitForTx = true).id
    sender.transactionInfo[TransactionInfo](setScriptId).script.get.startsWith("base64:") shouldBe true

    val scriptInfo = sender.addressScriptInfo(dApp)
    scriptInfo.scriptText.isEmpty shouldBe false
    scriptInfo.script.get.startsWith("base64:") shouldBe true
  }

  private def compile(scriptText: String): String =
    ScriptCompiler.compile(scriptText, ScriptEstimatorV3).explicitGet()._1.bytes().base64

  test("fail invoke script transaction if complexity exceeds fail-free limit") {
    val tx = sender.invokeScript(
      caller = sender.address,
      dappAddress = dApp,
      func = Some("default"),
      args = List(CONST_BOOLEAN(false)),
      waitForTx = true
    )
    sender.transactionStatus(Seq(tx._1.id)).head.status shouldBe "confirmed"
    sender.debugStateChanges(tx._1.id).stateChanges.get.error.get.text should include("failed")
  }

  test("reject invoke script transaction if complexity conforms fail-free limit") {
    val tx = sender.invokeScript(
      caller = sender.address,
      dappAddress = dApp,
      func = Some("default"),
      args = List(CONST_BOOLEAN(true))
    )
    sender.waitForHeight(sender.height + 1)
    sender.transactionStatus(Seq(tx._1.id)).head.status shouldBe "not_found"
    assertApiErrorRaised(
      sender.debugStateChanges(tx._1.id).stateChanges,
      StatusCodes.NotFound.intValue
    )
  }
} 
Example 8
Source File: CompositeHttpService.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.api.http

import akka.actor.ActorSystem
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._
import akka.http.scaladsl.server.directives.{DebuggingDirectives, LoggingMagnet}
import com.wavesplatform.settings.RestAPISettings
import com.wavesplatform.utils.ScorexLogging

case class CompositeHttpService(routes: Seq[ApiRoute], settings: RestAPISettings)(system: ActorSystem) extends ScorexLogging {

  private val redirectToSwagger = redirect("/api-docs/index.html", StatusCodes.PermanentRedirect)
  private val swaggerRoute: Route =
    (pathEndOrSingleSlash | path("swagger"))(redirectToSwagger) ~
      pathPrefix("api-docs") {
        pathEndOrSingleSlash(redirectToSwagger) ~
          path("swagger.json")(complete(patchedSwaggerJson)) ~
          getFromResourceDirectory("swagger-ui")
      }

  val compositeRoute: Route        = extendRoute(routes.map(_.route).reduce(_ ~ _)) ~ swaggerRoute ~ complete(StatusCodes.NotFound)
  val loggingCompositeRoute: Route = Route.seal(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 = if (settings.cors) respondWithHeader(`Access-Control-Allow-Origin`.*) else pass

  private def extendRoute(base: Route): Route = handleAllExceptions {
    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
  }

  private[this] lazy val patchedSwaggerJson = {
    import com.wavesplatform.Version
    import com.wavesplatform.account.AddressScheme
    import play.api.libs.json.{JsObject, Json}

    def chainIdString: String =
      if (Character.isAlphabetic(AddressScheme.current.chainId)) AddressScheme.current.chainId.toChar.toString
      else s"#${AddressScheme.current.chainId}"

    val json = Json.parse(getClass.getClassLoader.getResourceAsStream("swagger-ui/swagger.json")).as[JsObject]
    val patchedInfo = (json \ "info").as[JsObject] ++ Json.obj(
      "version" -> Version.VersionString,
      "title"   -> s"Waves Full Node ($chainIdString)"
    )
    json ++ Json.obj("info" -> patchedInfo)
  }
} 
Example 9
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 10
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 11
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
} 
Example 12
Source File: AuthenticationRouterSpec.scala    From akka-http-rest-api   with MIT License 5 votes vote down vote up
package authentication

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import core.ErrorWrapper
import token.TokenRepository
import user.UserRepository
import utils.{FlatSpecWithRedis, FlatSpecWithSql, BaseRoutesSpec}
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import UserAuthJsonProtocol._
import core.CommonJsonProtocol._
import org.scalatest.time.{Millis, Seconds, Span}

class AuthenticationRouterSpec extends BaseRoutesSpec with FlatSpecWithSql with FlatSpecWithRedis {
  spec =>

  override implicit val actorSystem: ActorSystem = spec.system

  val tokenRepo = new TokenRepository
  val userRepo = new UserRepository
  val userAuthRepo = new UserAuthRepository
  val userAuthService = new UserAuthService(tokenRepo, userAuthRepo, userRepo)

  val authRouter = new AuthenticationRouter with TestRoutesSupport {
    override val userAuthService = spec.userAuthService

    override implicit val redis = spec.redis
  }

  val routes = Route.seal(authRouter.authenticationRoutes)

  // how long it should wait before declaring that the future has timed out
  implicit val defaultPatience = PatienceConfig(timeout = Span(2, Seconds), interval = Span(50, Millis))

  "POST /register" should "register new user" in {
    Post("/auth/register", UserRegistrationRequest("[email protected]", "password", "Jan", "Kowalski", 1, 0)) ~> routes ~> check {
      userAuthRepo.findByUserEmail("[email protected]").futureValue should be('defined)
      status should be(StatusCodes.Created)
    }
  }

  "POST /register with invalid data" should "result in an error" in {
    Post("/auth/register") ~> routes ~> check {
      status should be(StatusCodes.BadRequest)
    }
  }

  "POST /register with an existing email" should "return 409 with an error message" in {
    userAuthService.register(UserRegistrationRequest("[email protected]", "password", "Jan", "Kowalski", 1, 0)).futureValue

    Post("/auth/register", UserRegistrationRequest("[email protected]", "password", "Jan", "Kowalski", 1, 0)) ~> routes ~> check {
      status should be(StatusCodes.Conflict)
      entityAs[ErrorWrapper].userMessage should be("E-mail already in use")
    }
  }

  "POST /login with valid data" should "result in login user" in {
    userAuthService.register(UserRegistrationRequest("[email protected]", "password", "Jan", "Kowalski", 1, 0)).futureValue

    Post("/auth/login", UserLoginRequest("[email protected]", "password")) ~> routes ~> check {
      status should be(StatusCodes.OK)
    }
  }

  "POST /login with invalid data" should "result in an error" in {
    Post("/auth/login") ~> routes ~> check {
      status should be(StatusCodes.BadRequest)
    }
  }

  "POST /login with invalid password" should "result in an error" in {
    userAuthService.register(UserRegistrationRequest("[email protected]", "password", "Jan", "Kowalski", 1, 0)).futureValue

    Post("/auth/login", UserLoginRequest("[email protected]", "pass")) ~> routes ~> check {
      status should be(StatusCodes.BadRequest)
      entityAs[ErrorWrapper].userMessage should be("Password is invalid")
    }
  }

  "POST /login with unknown email" should "result in an error" in {
    Post("/auth/login", UserLoginRequest("[email protected]", "password")) ~> routes ~> check {
      status should be(StatusCodes.BadRequest)
      entityAs[ErrorWrapper].userMessage should be("E-mail does not exist")
    }
  }

  "POST /auth/whatever" should "not be bound to /auth - reject unmatchedPath request" in {
    Post("/auth/whatever") ~> routes ~> check {
      status should be(StatusCodes.NotFound)
    }
  }
} 
Example 13
Source File: UpdateApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.atlas.aggregator

import javax.inject.Inject
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import com.fasterxml.jackson.core.JsonParser
import com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.core.validation.ValidationResult
import com.netflix.atlas.eval.stream.Evaluator
import com.typesafe.scalalogging.StrictLogging

class UpdateApi @Inject()(
  evaluator: Evaluator,
  aggrService: AtlasAggregatorService
) extends WebApi
    with StrictLogging {

  import UpdateApi._

  require(aggrService != null, "no binding for aggregate registry")

  def routes: Route = {
    endpointPath("api" / "v4" / "update") {
      post {
        parseEntity(customJson(p => processPayload(p, aggrService))) { response =>
          complete(response)
        }
      }
    }
  }
}

object UpdateApi {
  private val decoder = PayloadDecoder.default

  private[aggregator] def processPayload(
    parser: JsonParser,
    service: AtlasAggregatorService
  ): HttpResponse = {
    val result = decoder.decode(parser, service)
    createResponse(result.numDatapoints, result.failures)
  }

  private val okResponse = {
    val entity = HttpEntity(MediaTypes.`application/json`, "{}")
    HttpResponse(StatusCodes.OK, entity = entity)
  }

  private def createErrorResponse(status: StatusCode, msg: FailureMessage): HttpResponse = {
    val entity = HttpEntity(MediaTypes.`application/json`, msg.toJson)
    HttpResponse(status, entity = entity)
  }

  private def createResponse(numDatapoints: Int, failures: List[ValidationResult]): HttpResponse = {
    if (failures.isEmpty) {
      okResponse
    } else {
      val numFailures = failures.size
      if (numDatapoints > numFailures) {
        // Partial failure
        val msg = FailureMessage.partial(failures, numFailures)
        createErrorResponse(StatusCodes.Accepted, msg)
      } else {
        // All datapoints dropped
        val msg = FailureMessage.error(failures, numFailures)
        createErrorResponse(StatusCodes.BadRequest, msg)
      }
    }
  }
} 
Example 14
Source File: ExplainApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.atlas.druid

import akka.actor.ActorRefFactory
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.RouteResult
import akka.pattern.ask
import akka.util.Timeout
import com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.druid.ExplainApi.ExplainRequest
import com.netflix.atlas.eval.graph.Grapher
import com.netflix.atlas.json.Json
import com.netflix.atlas.webapi.GraphApi.DataRequest
import com.typesafe.config.Config

import scala.concurrent.duration._

class ExplainApi(config: Config, implicit val actorRefFactory: ActorRefFactory) extends WebApi {

  private val grapher: Grapher = Grapher(config)

  private val dbRef = actorRefFactory.actorSelection("/user/db")

  private implicit val ec = actorRefFactory.dispatcher

  override def routes: Route = {
    endpointPath("explain" / "v1" / "graph") {
      get { ctx =>
        val graphCfg = grapher.toGraphConfig(ctx.request)
        dbRef
          .ask(ExplainRequest(DataRequest(graphCfg)))(Timeout(10.seconds))
          .map { response =>
            val json = Json.encode(response)
            val entity = HttpEntity(MediaTypes.`application/json`, json)
            RouteResult.Complete(HttpResponse(StatusCodes.OK, entity = entity))
          }
      }
    }
  }
}

object ExplainApi {
  case class ExplainRequest(dataRequest: DataRequest)
} 
Example 15
Source File: StatsApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.iep.lwc

import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.json.Json


class StatsApi(evaluator: ExpressionsEvaluator) extends WebApi {

  override def routes: Route = {
    endpointPathPrefix("api" / "v1" / "stats") {
      get {
        val stats = Json.encode(evaluator.stats)
        val entity = HttpEntity(MediaTypes.`application/json`, stats)
        val response = HttpResponse(StatusCodes.OK, Nil, entity)
        complete(response)
      }
    }
  }
} 
Example 16
Source File: HealthEndpointsSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.health

import java.net.InetAddress

import akka.http.scaladsl.model.headers.{Accept, `Remote-Address`}
import akka.http.scaladsl.model.{ContentTypes, MediaTypes, RemoteAddress, StatusCodes}
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.routing.Rejection.NotFoundRejection
import org.specs2.mutable.Specification

import scala.concurrent.Future

class HealthEndpointsSpec extends Specification with Specs2RouteTest {

  sequential

  val endpoints = new HealthEndpoints()(system, system.dispatcher)
  def remoteAddress(ip: String) = RemoteAddress(InetAddress.getByName(ip))

  "The routing infrastructure" should {

    "support a call to /health" in {
      Get("/health").withHeaders(`Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        contentType === ContentTypes.`application/json`
        status must be equalTo (StatusCodes.OK)
      }
    }

    "support a call to /health that should return json" in {
      Get("/health").withHeaders(Accept(MediaTypes.`application/json`),
        `Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        mediaType === MediaTypes.`application/json`
        contentType === ContentTypes.`application/json`
      }
    }

    "a call to /health should return an error due to CIDR rules" in {
      Get("/health").withHeaders(Accept(MediaTypes.`application/json`),
        `Remote-Address`(remoteAddress("192.168.1.1"))) ~> endpoints.route ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }

    "support a call to /health/lb" in {
      Get("/health/lb").withHeaders(Accept(MediaTypes.`text/plain`),
        `Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        mediaType === MediaTypes.`text/plain`
        responseAs[String].equals("UP")
      }
    }

    "support a call to health/lb that returns a status of `Ok` when a health check is marked as degraded" in {
      Health(system).addCheck(new HealthCheck {
        override def getHealth: Future[HealthInfo] = Future {
          HealthInfo("degraded", HealthState.DEGRADED, "")
        }
      })

      Get("/health/lb").withHeaders(Accept(MediaTypes.`text/plain`),
        `Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        mediaType === MediaTypes.`text/plain`
        status === StatusCodes.OK
        responseAs[String].equals("UP")
      }
    }

    "support a call to health/lb that returns a status of `ServiceUnavailable` when a health check is marked as critical" in {
      Health(system).addCheck(new HealthCheck {
        override def getHealth: Future[HealthInfo] = Future {
          HealthInfo("critical", HealthState.CRITICAL, "")
        }
      })

      Get("/health/lb").withHeaders(Accept(MediaTypes.`text/plain`),
        `Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        //handled must beTrue
        mediaType === MediaTypes.`text/plain`
        status === StatusCodes.ServiceUnavailable
        responseAs[String].equals("DOWN")
      }
    }

  }
} 
Example 17
Source File: PersistenceApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.atlas.persistence

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 com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.DiagnosticMessage
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.webapi.PublishApi

class PersistenceApi(localFileService: LocalFilePersistService) extends WebApi {

  override def routes: Route = {
    post {
      endpointPath("api" / "v1" / "persistence") {
        handleReq
      } ~ endpointPath("api" / "v1" / "publish") {
        handleReq
      } ~ endpointPath("api" / "v1" / "publish-fast") {
        // Legacy path from when there was more than one publish mode
        handleReq
      }
    }
  }

  private def handleReq: Route = {
    parseEntity(customJson(p => PublishApi.decodeBatch(p))) { datapoints =>
      datapoints match {
        case Nil => complete(DiagnosticMessage.error(StatusCodes.BadRequest, "empty payload"))
        case _ => {
          datapoints.foreach(localFileService.persist)
          complete(HttpResponse(StatusCodes.OK))
        }
      }
    }
  }
} 
Example 18
Source File: PropertiesApi.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.iep.archaius

import java.io.StringWriter
import java.util.Properties

import akka.actor.ActorRefFactory
import akka.http.scaladsl.model.HttpCharsets
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.model.HttpEntity
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Route
import com.netflix.atlas.akka.CustomDirectives._
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.json.Json
import com.netflix.frigga.Names

class PropertiesApi(
  val propContext: PropertiesContext,
  implicit val actorRefFactory: ActorRefFactory
) extends WebApi {

  def routes: Route = {
    endpointPath("api" / "v1" / "property") {
      get {
        parameter("asg") { asg =>
          extractRequest { request =>
            val cluster = Names.parseName(asg).getCluster
            if (propContext.initialized) {
              val props = propContext.getClusterProps(cluster)
              complete(encode(request, props))
            } else {
              complete(HttpResponse(StatusCodes.ServiceUnavailable))
            }
          }
        }
      }
    }
  }

  private def encode(request: HttpRequest, props: List[PropertiesApi.Property]): HttpResponse = {
    val useJson = request.headers.exists(h => h.is("accept") && h.value == "application/json")
    if (useJson) {
      HttpResponse(
        StatusCodes.OK,
        entity = HttpEntity(MediaTypes.`application/json`, Json.encode(props))
      )
    } else {
      val ps = new Properties
      props.foreach { p =>
        ps.setProperty(p.key, p.value)
      }
      val writer = new StringWriter()
      ps.store(writer, s"count: ${ps.size}")
      writer.close()
      val entity =
        HttpEntity(MediaTypes.`text/plain`.toContentType(HttpCharsets.`UTF-8`), writer.toString)
      HttpResponse(StatusCodes.OK, entity = entity)
    }
  }
}

object PropertiesApi {
  case class Property(id: String, cluster: String, key: String, value: String, timestamp: Long)
} 
Example 19
Source File: PropertiesApiSuite.scala    From iep-apps   with Apache License 2.0 5 votes vote down vote up
package com.netflix.iep.archaius

import java.io.StringReader
import java.util.Properties

import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.model.MediaTypes
import akka.http.scaladsl.model.StatusCode
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.testkit.RouteTestTimeout
import akka.http.scaladsl.testkit.ScalatestRouteTest
import com.netflix.atlas.akka.RequestHandler
import com.netflix.atlas.json.Json
import com.netflix.spectator.api.DefaultRegistry
import com.netflix.spectator.api.ManualClock
import org.scalatest.funsuite.AnyFunSuite

class PropertiesApiSuite extends AnyFunSuite with ScalatestRouteTest {
  import scala.concurrent.duration._
  implicit val routeTestTimeout = RouteTestTimeout(5.second)

  val clock = new ManualClock()
  val registry = new DefaultRegistry(clock)
  val propContext = new PropertiesContext(registry)
  val endpoint = new PropertiesApi(propContext, system)
  val routes = RequestHandler.standardOptions(endpoint.routes)

  private def assertJsonContentType(response: HttpResponse): Unit = {
    assert(response.entity.contentType.mediaType === MediaTypes.`application/json`)
  }

  private def assertResponse(response: HttpResponse, expected: StatusCode): Unit = {
    assert(response.status === expected)
    assertJsonContentType(response)
  }

  test("no asg") {
    Get("/api/v1/property") ~> routes ~> check {
      assert(response.status === StatusCodes.BadRequest)
    }
  }

  test("empty") {
    propContext.update(Nil)
    Get("/api/v1/property?asg=foo-main-v001") ~>
    addHeader(Accept(MediaTypes.`application/json`)) ~>
    routes ~>
    check {
      assertResponse(response, StatusCodes.OK)
      assert(responseAs[String] === "[]")
    }
  }

  test("properties response") {
    propContext.update(
      List(
        PropertiesApi.Property("foo-main::a", "foo-main", "a", "b", 12345L),
        PropertiesApi.Property("foo-main::1", "foo-main", "1", "2", 12345L),
        PropertiesApi.Property("bar-main::c", "bar-main", "c", "d", 12345L)
      )
    )
    Get("/api/v1/property?asg=foo-main-v001") ~> routes ~> check {
      assert(response.status === StatusCodes.OK)
      val props = new Properties
      props.load(new StringReader(responseAs[String]))
      assert(props.size === 2)
      assert(props.getProperty("a") === "b")
      assert(props.getProperty("1") === "2")
    }
  }

  test("json response") {
    propContext.update(
      List(
        PropertiesApi.Property("foo-main::a", "foo-main", "a", "b", 12345L)
      )
    )
    Get("/api/v1/property?asg=foo-main-v001") ~>
    addHeader(Accept(MediaTypes.`application/json`)) ~>
    routes ~>
    check {
      assertResponse(response, StatusCodes.OK)
      val props = Json.decode[List[PropertiesApi.Property]](responseAs[String])
      assert(props === List(PropertiesApi.Property("foo-main::a", "foo-main", "a", "b", 12345L)))
    }
  }
} 
Example 20
Source File: RateLimit.scala    From twitter4s   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.twitter4s.entities

import java.time.Instant

import akka.http.scaladsl.model.{HttpHeader, StatusCodes}
import com.danielasfregola.twitter4s.exceptions.TwitterException

final case class RateLimit(limit: Int, remaining: Int, reset: Instant)

object RateLimit {

  def apply(limit: Int, remaining: Int, reset: Long): RateLimit =
    apply(limit, remaining, Instant.ofEpochSecond(reset))

  def apply(headers: Seq[HttpHeader]): RateLimit = {
    val errorMsg =
      s"""Rate Information expected but not found.
         |
         |Please report it at https://github.com/DanielaSfregola/twitter4s/issues/new
         |Headers names were: ${headers.map(_.lowercaseName).mkString(", ")}""".stripMargin

    def extractHeaderValue[T](name: String)(f: String => T): T =
      headers
        .find(_.lowercaseName == name)
        .map(h => f(h.value))
        .getOrElse(throw TwitterException(StatusCodes.InternalServerError, errorMsg))

    val limit = extractHeaderValue("x-rate-limit-limit")(_.toInt)
    val remaining = extractHeaderValue("x-rate-limit-remaining")(_.toInt)
    val reset = extractHeaderValue("x-rate-limit-reset")(_.toLong)
    apply(limit, remaining, reset)
  }

} 
Example 21
Source File: FormSupport.scala    From twitter4s   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.twitter4s.http.serializers

import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.stream.Materializer
import com.danielasfregola.twitter4s.exceptions.TwitterException

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

private[twitter4s] trait FromMap[T] {
  def apply(m: Map[String, String]): Option[T]

  def toBoolean(text: String): Boolean = text.trim.toLowerCase == "true"
}

private[twitter4s] object FormSupport {

  def unmarshallText[T: Manifest](response: HttpResponse)(implicit materializer: Materializer,
                                                          fromMap: FromMap[T]): Future[T] = {
    implicit val ec = materializer.executionContext
    response.entity.toStrict(5 seconds).map(_.data.decodeString("UTF-8")).map { body =>
      fromMap(asMap(body)).getOrElse(throw unmarshallError[T](body))
    }
  }

  private def asMap(body: String): Map[String, String] =
    body
      .split("&")
      .map { fields =>
        val tokens = fields.split("=", 2)
        tokens.head -> tokens.tail.mkString.trim
      }
      .toMap

  private def unmarshallError[T: Manifest](body: String): TwitterException = {
    val errorMsg =
      s"""Could not serialise body to ${manifest[T].runtimeClass.getSimpleName}.
         |
         |Please report it at https://github.com/DanielaSfregola/twitter4s/issues/new
         |Body was: $body""".stripMargin
    TwitterException(StatusCodes.InternalServerError, errorMsg)
  }
} 
Example 22
Source File: RestClientSpec.scala    From twitter4s   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.twitter4s.http.clients.rest

import akka.http.scaladsl.model.{ContentTypes, HttpResponse, StatusCodes}
import com.danielasfregola.twitter4s.exceptions.{Errors, TwitterError, TwitterException}
import com.danielasfregola.twitter4s.helpers.ClientSpec

import scala.concurrent.Future

class RestClientSpec extends ClientSpec {

  class ClientSpecContext extends RestClientSpecContext {
    import restClient._

    def exampleRequest(): Future[Unit] = Get("an-example-request", ContentTypes.`application/json`).respondAs[Unit]
  }

  "Rest Client" should {

    "throw twitter exception to twitter rejection" in new ClientSpecContext {
      val response = {
        val entity = """{"errors":[{"message":"Sorry, that page does not exist","code":34}]}"""
        HttpResponse(StatusCodes.NotFound, entity = entity)
      }
      val result = when(exampleRequest).expectRequest(identity(_)).respondWith(response)
      val expectedTwitterException = TwitterException(code = StatusCodes.NotFound,
                                                      errors =
                                                        Errors(TwitterError("Sorry, that page does not exist", 34)))
      result.await should throwAn(expectedTwitterException)
    }

    "throw twitter exception to generic failure http response" in new ClientSpecContext {
      val body = "Something bad happened"
      val response = HttpResponse(StatusCodes.RequestTimeout, entity = body)
      val result = when(exampleRequest).expectRequest(identity(_)).respondWith(response)
      val expectedTwitterException = TwitterException(code = StatusCodes.RequestTimeout, errors = Errors(body))

      result.await should throwAn(expectedTwitterException)
    }

  }

} 
Example 23
Source File: SwaggerAkka.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.swagger.akkahttp

import java.util.Properties

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


class SwaggerAkka(yaml: String, contextPath: String = "docs", yamlName: String = "docs.yaml") {
  private val redirectToIndex: Route =
    redirect(s"/$contextPath/index.html?url=/$contextPath/$yamlName", StatusCodes.PermanentRedirect)

  // needed only if you use oauth2 authorization
  private def redirectToOath2(query: String): Route =
    redirect(s"/$contextPath/oauth2-redirect.html$query", StatusCodes.PermanentRedirect)

  private val swaggerVersion = {
    val p = new Properties()
    val pomProperties = getClass.getResourceAsStream("/META-INF/maven/org.webjars/swagger-ui/pom.properties")
    try p.load(pomProperties)
    finally pomProperties.close()
    p.getProperty("version")
  }

  val routes: Route =
    pathPrefix(contextPath) {
      pathEndOrSingleSlash {
        redirectToIndex
      } ~ path(yamlName) {
        complete(yaml)
      } ~ getFromResourceDirectory(s"META-INF/resources/webjars/swagger-ui/$swaggerVersion/")
    } ~
      // needed only if you use oauth2 authorization
      path("oauth2-redirect.html") { request =>
        redirectToOath2(request.request.uri.rawQueryString.map(s => "?" + s).getOrElse(""))(request)
      }
} 
Example 24
Source File: RedocAkkaHttp.scala    From tapir   with Apache License 2.0 5 votes vote down vote up
package sttp.tapir.redoc.akkahttp

import akka.http.scaladsl.model.{ContentTypes, HttpCharsets, HttpEntity, MediaType, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route

class RedocAkkaHttp(title: String, yaml: String, yamlName: String = "docs.yaml", redocVersion: String = "2.0.0-rc.23") {
  lazy val html: String =
    s"""
       |<!DOCTYPE html>
       |<html>
       |<head>
       |  <title>${title}</title>
       |  <!-- needed for adaptive design -->
       |  <meta charset="utf-8"/>
       |  <meta name="viewport" content="width=device-width, initial-scale=1">
       |  <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
       |
       |  <!--
       |  ReDoc doesn't change outer page styles
       |  -->
       |  <style>
       |    body {
       |      margin: 0;
       |      padding: 0;
       |    }
       |  </style>
       |</head>
       |<body>
       |<redoc spec-url='${yamlName}' expand-responses="200,201"></redoc>
       |<script src="https://cdn.jsdelivr.net/npm/redoc@${redocVersion}/bundles/redoc.standalone.js"></script>
       |</body>
       |</html>
       |""".stripMargin

  def routes: Route = {
    get {
      pathEnd {
        redirectToTrailingSlashIfMissing(StatusCodes.MovedPermanently) {
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
        }
      } ~ pathSingleSlash {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
      } ~ path(yamlName) {
        complete(HttpEntity(MediaType.textWithFixedCharset("yaml", HttpCharsets.`UTF-8`), yaml))
      }
    }
  }

} 
Example 25
Source File: Api.scala    From full-scala-stack   with Apache License 2.0 5 votes vote down vote up
package api

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.directives.DebuggingDirectives
import akka.http.scaladsl.server.{ Directives, Route, RouteConcatenation }
import core.{ Core, CoreActors }
import routes.{ HTMLRoute, ModelRoutes }


trait Api
    extends RouteConcatenation
    with Directives
    with LiveEnvironment
    with HTMLRoute
    with ModelRoutes
    with ZIODirectives {
  this: CoreActors with Core =>

  private implicit val _ = actorSystem.dispatcher

  //TODO This particular example app doesn't use sessions, look up "com.softwaremill.akka-http-session" if you want sessions
  val sessionResult = Option("validsession")

  val routes: Route = DebuggingDirectives.logRequest("Request") {
    extractLog { log =>
      unauthRoute ~ {
        extractRequestContext { requestContext =>
          sessionResult match {
            case Some(session) =>
              apiRoute(session)
            case None =>
              log.info(
                s"Unauthorized request of ${requestContext.unmatchedPath}, redirecting to login"
              )
              redirect("/loginForm", StatusCodes.Found)
          }
        }
      } ~
      htmlRoute
    }
  }
} 
Example 26
Source File: BasicAuthenticationTest.scala    From sumobot   with Apache License 2.0 5 votes vote down vote up
package com.sumologic.sumobot.http_frontend.authentication

import akka.http.scaladsl.model.HttpMethods.{GET, POST}
import akka.http.scaladsl.model.{HttpRequest, StatusCodes, Uri}
import com.sumologic.sumobot.test.annotated.SumoBotSpec
import akka.http.scaladsl.model.headers._
import com.typesafe.config.ConfigFactory
import scala.collection.JavaConverters._

class BasicAuthenticationTest extends SumoBotSpec {
  private val authConfig = ConfigFactory.parseMap(
    Map("username" -> "admin", "password" -> "hunter2").asJava)
  val basicAuthentication = new BasicAuthentication(authConfig)
  val base64Credentials = "YWRtaW46aHVudGVyMg=="
  val base64InvalidCredentials = "YWRtaW46aHVpdGVyMg=="

  val rootRequest = HttpRequest(GET, Uri("/"))
  val authorizedRootRequest = rootRequest.withHeaders(List(`Authorization`(GenericHttpCredentials("basic", base64Credentials))))
  val invalidRootRequest = rootRequest.withHeaders(List(`Authorization`(GenericHttpCredentials("basic", base64InvalidCredentials))))

  "BasicAuthentication" should {
      "return 401 Unauthorized" when {
        "unauthenticated" in {
          val result = basicAuthentication.authentication(rootRequest)
          result match {
            case AuthenticationForbidden(response) =>
              response.status should be(StatusCodes.Unauthorized)
              response.header[`WWW-Authenticate`].nonEmpty should be(true)
            case _ =>
              fail("expected AuthenticationForbidden")
          }
        }
      }

    "successfuly authenticate" when {
      "provided correct Authorization header" in {
        val result = basicAuthentication.authentication(authorizedRootRequest)
        result match {
          case AuthenticationSucceeded(info) =>
            info.authMessage match {
              case Some(message) =>
                message should include("admin")
              case _ => fail("expected authMessage")
            }
          case _ =>
            fail("expected AuthenticationSucceeded")
        }
      }
    }

    "return 403 Forbidden" when {
      "provided incorrect Authorization header" in {
        val result = basicAuthentication.authentication(invalidRootRequest)
        result match {
          case AuthenticationForbidden(response) =>
            response.status should be(StatusCodes.Forbidden)
          case _ =>
            fail("expected AuthenticationForbidden")
        }
      }
    }
  }
} 
Example 27
Source File: package.scala    From akka-cluster-manager   with MIT License 5 votes vote down vote up
package io.orkestra.cluster

import akka.actor.ActorRef
import akka.http.scaladsl.model.{StatusCodes, StatusCode}
import play.api.libs.json.{JsString, Format, Json, JsValue}

package object protocol {

  case class Register(member: ActorRef, role: String)
  case class RegisterInternal(member: ActorRef, role: String)

  sealed trait Response {
    def asJson: JsValue
    def httpStatusCode: StatusCode
  }

  object Response {

    trait Success extends Response {
      override val httpStatusCode: StatusCode = StatusCodes.OK
    }

    object Success {

      case class Router(name: String, routees: List[String]) extends Success {
        override val asJson = Json.toJson(this)
      }
      object Router {
        implicit val fmt: Format[Router] = Json.format[Router]
      }

      case class Routers(routers: Iterable[JsValue]) extends Success {
        override val asJson = Json.toJson(routers)
      }

      case class RouteeDeleted(role: String, path: String) extends Success {
        override val asJson = JsString(s"routee: $path with role: $role successfully deleted")
      }

    }

    trait Failure extends Response

    object Failure {
      case class RouterNotFound(role: String) extends Failure {
        override val httpStatusCode: StatusCode = StatusCodes.NotFound
        override val asJson: JsValue = Json.obj("error" -> s"router with role: $role not found")
      }
    }
  }

} 
Example 28
Source File: HttpManagementServer.scala    From akka-cluster-manager   with MIT License 5 votes vote down vote up
package io.orkestra.cluster.management

import java.util.concurrent.atomic.AtomicReference

import akka.Done
import akka.actor.{ActorSystem, ActorRef}
import akka.cluster.Cluster
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.stream.{ActorMaterializer, Materializer}
import io.orkestra.cluster.protocol.Response.{Failure, Success}
import io.orkestra.cluster.routing.ClusterListener._
import akka.pattern.ask
import play.api.libs.json.Json
import scala.concurrent.{Promise, Future, ExecutionContext}
import scala.concurrent.duration._

class HttpManagementServer(clusterListener: ActorRef, hostName: String = "127.0.0.1", port: Int = 33333)(
    implicit
    val system:                ActorSystem,
    implicit val materializer: Materializer,
    implicit val executer:     ExecutionContext
) {

  import PlayJsonSupport._

  def handleOrkestraRequest(req: ManagementReguest) =
    (clusterListener ? req)(3.seconds).map {
      case res: Success =>
        res.httpStatusCode -> res.asJson
      case res: Failure =>
        res.httpStatusCode -> res.asJson
    }

  def orkestraRoutes =
    pathPrefix("orkestra" / "routers") {
      pathEndOrSingleSlash {
        get {
          complete(handleOrkestraRequest(GetRouters))
        }
      } ~
        path(Segment ~ Slash.?) { role =>
          get {
            complete(handleOrkestraRequest(GetRouter(role)))
          }
        } ~
        path(Segment / Remaining ~ Slash.?) { (role, routeePath) =>
          delete {
            complete(handleOrkestraRequest(DeleteRoutee(role, routeePath)))
          }
        }
    }

  private val bindingFuture = new AtomicReference[Future[Http.ServerBinding]]()

  def start() = {
    val serverBindingPromise = Promise[Http.ServerBinding]()
    if (bindingFuture.compareAndSet(null, serverBindingPromise.future)) {
      Http().bindAndHandle(orkestraRoutes, hostName, port)
      println(Console.CYAN + s"cluster http management server online at http://${hostName}:${port}/" + Console.WHITE)
    }
  }

  def shutdown =
    if (bindingFuture.get() == null) {
      Future(Done)
    } else {
      val stopFuture = bindingFuture.get().flatMap(_.unbind()).map(_ => Done)
      bindingFuture.set(null)
      stopFuture
    }

} 
Example 29
Source File: BasicAuthenticationSpec.scala    From scruid   with Apache License 2.0 5 votes vote down vote up
package ing.wbaa.druid.auth.basic

import scala.concurrent.duration._
import scala.language.postfixOps

import akka.http.scaladsl.model.StatusCodes
import ing.wbaa.druid.{ DruidConfig, QueryHost, TimeSeriesQuery }
import ing.wbaa.druid.client.{ DruidAdvancedHttpClient, HttpStatusException }
import ing.wbaa.druid.definitions._
import io.circe.generic.auto._
import org.scalatest.concurrent._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class BasicAuthenticationSpec extends AnyWordSpec with Matchers with ScalaFutures {

  override implicit def patienceConfig: PatienceConfig = PatienceConfig(5 minutes, 100 millis)
  private val totalNumberOfEntries                     = 39244
  private val basicAuthenticationAddition =
    new BasicAuthenticationExtension(username = "user", password = "aloha")

  case class TimeseriesCount(count: Int)

  "TimeSeriesQuery without Basic Auth" should {

    implicit val config = DruidConfig(
      clientBackend = classOf[DruidAdvancedHttpClient],
      clientConfig = DruidAdvancedHttpClient
        .ConfigBuilder()
        .build(),
      hosts = Seq(QueryHost("localhost", 8088))
    )

    "get 401 Auth Required when querying Druid without Authentication config" in {
      val request = TimeSeriesQuery(
        aggregations = List(
          CountAggregation(name = "count")
        ),
        granularity = GranularityType.Hour,
        intervals = List("2011-06-01/2017-06-01")
      ).execute

      whenReady(request.failed) { throwable =>
        throwable shouldBe a[HttpStatusException]
        throwable.asInstanceOf[HttpStatusException].status shouldBe StatusCodes.Unauthorized
      }
    }
  }

  "TimeSeriesQuery with Basic Auth" should {

    implicit val config = DruidConfig(
      clientBackend = classOf[DruidAdvancedHttpClient],
      clientConfig = DruidAdvancedHttpClient
        .ConfigBuilder()
        .withRequestInterceptor(basicAuthenticationAddition)
        .build(),
      hosts = Seq(QueryHost("localhost", 8088))
    )

    "successfully query Druid when an Authentication config is set" in {
      val request = TimeSeriesQuery(
        aggregations = List(
          CountAggregation(name = "count")
        ),
        granularity = GranularityType.Hour,
        intervals = List("2011-06-01/2017-06-01")
      ).execute

      whenReady(request) { response =>
        response.list[TimeseriesCount].map(_.count).sum shouldBe totalNumberOfEntries
      }
    }
  }

} 
Example 30
Source File: JavaFlowSvcSpec.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.model.HttpEntity.Chunked
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import akka.pattern._
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Keep, Sink, Source}
import akka.testkit.TestKit
import com.typesafe.config.ConfigFactory
import org.scalatest.{AsyncFlatSpecLike, BeforeAndAfterAll, Matchers}
import org.squbs.lifecycle.GracefulStop
import org.squbs.unicomplex.Timeouts._

object JavaFlowSvcSpec {

  val classPaths = Array(getClass.getClassLoader.getResource("classpaths/JavaFlowSvc").getPath)

  val config = ConfigFactory.parseString(
    s"""
       |default-listener.bind-port = 0
       |squbs {
       |  actorsystem-name = JavaFlowSvcSpec
       |  ${JMX.prefixConfig} = true
       |}
    """.stripMargin
  )

  val boot = UnicomplexBoot(config)
    .createUsing {(name, config) => ActorSystem(name, config)}
    .scanComponents(classPaths)
    .initExtensions.start()
}

class JavaFlowSvcSpec extends TestKit(
  JavaFlowSvcSpec.boot.actorSystem) with AsyncFlatSpecLike with BeforeAndAfterAll with Matchers {

  implicit val am = ActorMaterializer()

  val portBindingsF = (Unicomplex(system).uniActor ? PortBindings).mapTo[Map[String, Int]]
  val portF = portBindingsF map { bindings => bindings("default-listener") }

  override def afterAll(): Unit = {
    Unicomplex(system).uniActor ! GracefulStop
  }

  it should "handle a normal request" in {
    for {
      port <- portF
      response <- entityAsString(s"http://127.0.0.1:$port/javaflowsvc/ping")
    } yield {
      response shouldBe "pong"
    }
  }

  it should "handle a chunked request and be able to provide a chunked response" in {
    val requestChunks = Source.single("Hi this is a test")
      .mapConcat { s => s.split(' ').toList }
      .map(HttpEntity.ChunkStreamPart(_))

    for {
      port <- portF
      response <- post(s"http://127.0.0.1:$port/javaflowsvc/chunks",
                       Chunked(ContentTypes.`text/plain(UTF-8)`, requestChunks))
      responseString <- response.entity.dataBytes.map(_.utf8String).toMat(Sink.fold("") { _ + _})(Keep.right).run()
    } yield {
      response.entity shouldBe 'chunked
      responseString should be("Received 5 chunks and 13 bytes.\r\nThis is the last chunk!")
    }
  }

  it should "get an InternalServerError with blank response if Flow collapses" in {
    for {
      port <- portF
      errResp <- get(s"http://127.0.0.1:$port/javaflowsvc/throwit")
      respEntity <- errResp.entity.toStrict(awaitMax)
    } yield {
      errResp.status shouldBe StatusCodes.InternalServerError
      respEntity.data.utf8String shouldBe 'empty
    }
  }
} 
Example 31
Source File: PrometheusRoutingSpec.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route

import akka.http.scaladsl.model.{HttpProtocol, HttpResponse, StatusCodes}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import io.prometheus.client.CollectorRegistry
import io.prometheus.client.dropwizard.DropwizardExports
import org.scalatestplus.mockito.MockitoSugar
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import org.scalatest.BeforeAndAfterEach
import vinyldns.core.VinylDNSMetrics

class PrometheusRoutingSpec
    extends AnyWordSpec
    with ScalatestRouteTest
    with PrometheusRoute
    with BeforeAndAfterEach
    with MockitoSugar
    with Matchers {

  val metricRegistry = VinylDNSMetrics.metricsRegistry

  val collectorRegistry = CollectorRegistry.defaultRegistry

  collectorRegistry.register(new DropwizardExports(metricRegistry))

  "GET /metrics/prometheus" should {
    "return metrics logged in prometheus" in {
      Get("/metrics/prometheus") ~> prometheusRoute ~> check {
        response.status shouldBe StatusCodes.OK
        val resultStatus = responseAs[HttpResponse]
        resultStatus.protocol shouldBe HttpProtocol("HTTP/1.1")
      }
    }
  }
} 
Example 32
Source File: BlueGreenRoutingSpec.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class BlueGreenRoutingSpec
    extends AnyWordSpec
    with ScalatestRouteTest
    with BlueGreenRoute
    with Matchers {

  def actorRefFactory: ActorSystem = system

  "GET color" should {
    "return blue" in {
      Get("/color") ~> colorRoute ~> check {
        response.status shouldBe StatusCodes.OK

        // set in the application.conf in src/test/resources
        responseAs[String] shouldBe "blue"
      }
    }
  }
} 
Example 33
Source File: HealthCheckRoutingSpec.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.testkit.ScalatestRouteTest
import org.mockito.Mockito.doReturn
import org.scalatestplus.mockito.MockitoSugar
import org.scalatest.OneInstancePerTest
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import cats.effect._
import vinyldns.core.health.HealthCheck.HealthCheckError
import vinyldns.core.health.HealthService

class HealthCheckRoutingSpec
    extends AnyWordSpec
    with ScalatestRouteTest
    with HealthCheckRoute
    with OneInstancePerTest
    with Matchers
    with MockitoSugar {

  val healthService: HealthService = mock[HealthService]

  "GET on the healthcheck" should {
    "return OK when all datastores return a positive result" in {
      doReturn(IO.pure(List())).when(healthService).checkHealth()
      Get("/health") ~> healthCheckRoute ~> check {
        status shouldBe StatusCodes.OK
      }
    }

    "return a 500 when the zone manager returns any error" in {
      val err = HealthCheckError("an error!")
      doReturn(IO.pure(List(err))).when(healthService).checkHealth()
      Get("/health") ~> healthCheckRoute ~> check {
        status shouldBe StatusCodes.InternalServerError
      }
    }
  }
} 
Example 34
Source File: PermissionSpec.scala    From akka-http-extensions   with Mozilla Public License 2.0 5 votes vote down vote up
package akka.http.extensions


import java.util.UUID

import akka.http.extensions.security._
import akka.http.extensions.stubs.{InMemorySessionController, InMemoryLoginController}
import akka.http.scaladsl.model.{DateTime, StatusCodes}
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.headers.{HttpCookie, Cookie, `Set-Cookie`}
import akka.http.scaladsl.server._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.{WordSpec}
import scala.collection.mutable
import scala.concurrent.Future
import scala.concurrent.duration._
import com.github.t3hnar.bcrypt._


class PermissionSpec extends ExtensionsTestBase with PermissionControllers
{
  "application with authorization" should{
    "check permissions" in {
      val loginController = new TestLoginController
      val sessionController = new TestSessionController
      import akka.http.scaladsl.server._
      val logins = new Logins(loginController, sessionController)
      val routes = logins.routes
      Put("/users/register?username=anton&password=test2test&[email protected]") ~> Route.seal(routes) ~> check {
        status shouldEqual OK
      }

      val permission = new Permissions(sessionController,loginController)

      Put("/add/drug?name=potion1") ~> permission.routes ~> check {
        rejection
      }

      Put("/users/[email protected]&password=test2test") ~> logins.routes ~> check {
        status shouldEqual OK
      }

      val antonToken = sessionController.tokenByUsername(anton.username).get

      Put("/add/drug?name=potion1&kind=user") ~> Cookie("X-Token" -> antonToken) ~> permission.routes ~> check {
        status shouldEqual OK
        responseAs[String] shouldEqual s"drug potion1 added!"
        permission.drugs.contains("potion1") shouldEqual true
      }

      Put("/add/drug?name=potion2&kind=user") ~> permission.routes ~> check {
        rejection
      }

      val antonR = sessionController.userByToken(antonToken).get //get user with hashed password
      permission.add2realm(antonR,VIPRealm)

      permission.checkRights(antonR,SpecialRealm) shouldEqual false
      permission.checkRights(antonR,VIPRealm) shouldEqual true


      Put(s"/users/register?username=${liz.username}&password=${liz.password}&email=${liz.email}") ~> Route.seal(routes) ~> check {
        status shouldEqual OK
      }

      val lizToken =  sessionController.tokenByUsername(liz.username).get
      val lizR = sessionController.userByToken(lizToken).get

      permission.add2realm(lizR,SpecialRealm)
      permission.checkRights(lizR,SpecialRealm) shouldEqual true
      permission.checkRights(lizR,VIPRealm) shouldEqual false


    Put("/add/drug?name=potion2&kind=special") ~> Cookie("X-Token" -> antonToken) ~> permission.routes ~> check {
      permission.drugs.contains("potion2") shouldEqual false
      rejection
    }
    Put("/add/drug?name=potion2&kind=special") ~> Cookie("X-Token" -> lizToken) ~> permission.routes ~> check {
      status shouldEqual OK
      permission.drugs.contains("potion2") shouldEqual true
      responseAs[String] shouldEqual s"drug potion2 added!"
    }

    Put("/add/drug?name=potion3&kind=vip") ~> Cookie("X-Token" -> lizToken) ~> permission.routes ~> check {
    //  permission.drugs.contains("potion3") shouldEqual false
      rejection
    }
    Put("/add/drug?name=potion3&kind=vip") ~> Cookie("X-Token" -> antonToken) ~> permission.routes ~> check {
      status shouldEqual OK
      permission.drugs.contains("potion3") shouldEqual true
      responseAs[String] shouldEqual s"drug potion3 added!"
   }
  }
}

} 
Example 35
Source File: CorsDirective.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.HttpMethods._
import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.{HttpHeader, HttpRequest, StatusCodes}
import akka.http.scaladsl.server.Directives.handleRejections
import akka.http.scaladsl.server._

import scala.collection.immutable._

trait CorsDirective {

  import Directives._
  import StatusCodes._
  import scala.concurrent.ExecutionContext.Implicits.global


  private val defaultHeaders = Seq(
    `Access-Control-Allow-Origin`.*,
    `Access-Control-Allow-Methods`(Seq(GET, POST, PUT, DELETE, HEAD, OPTIONS))
  )


  // old akka-http doesn't have build-in rejection response mapping method
  private val rejectionsHandler = new RejectionHandler {

    val original = RejectionHandler.default

    override def apply(rejections: Seq[Rejection]): Option[Route] = {
      original(rejections).map(route => route.andThen(_.map({
        case c @ RouteResult.Complete(r) =>
          RouteResult.Complete(r.withHeaders(defaultHeaders))
        case x => x
      })))
    }
  }

  def cors(): Directive0 = extractRequest.flatMap(request => {
    val headers = corsHeaders(request)
    if (request.method == OPTIONS) {
      respondWithHeaders(headers) & complete(OK, "Preflight response")
    } else {
      extractSettings.flatMap(routeSettings => {
        handleRejections(rejectionsHandler) &
        respondWithHeaders(headers) &
        handleExceptions(ExceptionHandler.default(routeSettings)) &
        pass
      })
    }
  })

  private def corsHeaders(request: HttpRequest): Seq[HttpHeader] = {
    val accessed = request.header[`Access-Control-Request-Headers`].map(_.headers).getOrElse(Seq.empty)
    val allowHeaders = `Access-Control-Allow-Headers`(accessed)
    allowHeaders +: defaultHeaders
  }

}

object CorsDirective extends CorsDirective 
Example 36
Source File: DevApi.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.marshalling
import akka.http.scaladsl.model
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives
import akka.http.scaladsl.server.directives.ParameterDirectives
import cats.data._
import cats.implicits._
import io.hydrosphere.mist.master.{JobDetails, MainService}
import io.hydrosphere.mist.master.interfaces.JsonCodecs
import io.hydrosphere.mist.master.interfaces.http.HttpV2Base.completeOpt
import io.hydrosphere.mist.master.models.DevJobStartRequestModel


object DevApi {

  import Directives._
  import JsonCodecs._
  import ParameterDirectives.ParamMagnet
  import akka.http.scaladsl.server._

  import scala.concurrent.ExecutionContext.Implicits.global

  def devRoutes(masterService: MainService): Route = {
    val exceptionHandler =
      ExceptionHandler {
        case iae: IllegalArgumentException =>
          complete((StatusCodes.BadRequest, s"Bad request: ${iae.getMessage}"))
        case ex =>
          complete(HttpResponse(StatusCodes.InternalServerError, entity = s"Server error: ${ex.getMessage}"))
      }
    path( "v2" / "hidden" / "devrun" ) {
      post( parameter('force ? false) { force =>
        entity(as[DevJobStartRequestModel]) { req =>
          handleExceptions(exceptionHandler) {
            val execInfo = masterService.devRun(req.toCommon, JobDetails.Source.Http)
            if (force)
              complete(execInfo.map(_.toJobResult))
            else
              complete(execInfo.map(_.toJobStartResponse))
          }
        }
      })
    }
  }
} 
Example 37
Source File: DevApiSpec.scala    From mist   with Apache License 2.0 5 votes vote down vote up
package io.hydrosphere.mist.master.interfaces.http

import mist.api.data._
import mist.api.encoding.JsSyntax._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import io.hydrosphere.mist.core.CommonData.{JobParams, RunJobRequest}
import io.hydrosphere.mist.core.MockitoSugar
import io.hydrosphere.mist.core.CommonData.Action
import io.hydrosphere.mist.master.JobDetails.{Source, Status}
import io.hydrosphere.mist.master.execution.ExecutionInfo
import io.hydrosphere.mist.master.MainService
import io.hydrosphere.mist.master.interfaces.JsonCodecs
import io.hydrosphere.mist.master.models.{DevJobStartRequest, DevJobStartRequestModel}
import org.scalatest.{FunSpec, Matchers}

import scala.concurrent.Promise

class DevApiSpec extends FunSpec with Matchers with ScalatestRouteTest with MockitoSugar {

  import JsonCodecs._
  import io.hydrosphere.mist.master.TestUtils._

  it("should start job in dev mode") {
    val master = mock[MainService]
    val api = DevApi.devRoutes(master)

    val req = DevJobStartRequestModel("simple-context", "path", "className", None, None, None, "foo")

    val promise = Promise[JsData]
    promise.success(JsUnit)

    when(master.devRun(any[DevJobStartRequest], any[Source], any[Action]))
      .thenSuccess(ExecutionInfo(
        RunJobRequest("id", JobParams("path", "className", JsMap.empty, Action.Execute)),
        promise
      ))

    Post("/v2/hidden/devrun", req) ~> api ~> check {
      status shouldBe StatusCodes.OK
    }
  }
} 
Example 38
Source File: ServiceHandler.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package akka.grpc.scaladsl

import akka.annotation.ApiMayChange
import akka.grpc.GrpcProtocol
import akka.grpc.internal.{ GrpcProtocolNative, GrpcProtocolWeb, GrpcProtocolWebText }
import akka.http.javadsl.{ model => jmodel }
import akka.http.scaladsl.model.{ HttpRequest, HttpResponse, StatusCodes }

import scala.concurrent.Future

@ApiMayChange
object ServiceHandler {

  private[scaladsl] val notFound: Future[HttpResponse] = Future.successful(HttpResponse(StatusCodes.NotFound))

  private[scaladsl] val unsupportedMediaType: Future[HttpResponse] =
    Future.successful(HttpResponse(StatusCodes.UnsupportedMediaType))

  private def matchesVariant(variants: Set[GrpcProtocol])(request: jmodel.HttpRequest) =
    variants.exists(_.mediaTypes.contains(request.entity.getContentType.mediaType))

  private[grpc] val isGrpcRequest: jmodel.HttpRequest => Boolean = matchesVariant(Set(GrpcProtocolNative))
  private[grpc] val isGrpcWebRequest: jmodel.HttpRequest => Boolean = matchesVariant(
    Set(GrpcProtocolWeb, GrpcProtocolWebText))

  def concatOrNotFound(
      handlers: PartialFunction[HttpRequest, Future[HttpResponse]]*): HttpRequest => Future[HttpResponse] =
    concat(handlers: _*).orElse { case _ => notFound }

  def concat(handlers: PartialFunction[HttpRequest, Future[HttpResponse]]*)
      : PartialFunction[HttpRequest, Future[HttpResponse]] =
    handlers.foldLeft(PartialFunction.empty[HttpRequest, Future[HttpResponse]]) {
      case (acc, pf) => acc.orElse(pf)
    }
} 
Example 39
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 40
Source File: AkkaHttpActionAdapter.scala    From akka-http-pac4j   with Mozilla Public License 2.0 5 votes vote down vote up
package com.stackstate.pac4j.http

import akka.http.scaladsl.model.{HttpEntity, HttpHeader, HttpResponse, StatusCodes, Uri}
import org.pac4j.core.context.HttpConstants
import org.pac4j.core.http.adapter.HttpActionAdapter
import akka.http.scaladsl.model.StatusCodes._
import akka.http.scaladsl.model.headers.Location
import akka.http.scaladsl.server.RouteResult
import akka.http.scaladsl.server.RouteResult.Complete
import com.stackstate.pac4j.AkkaHttpWebContext
import org.pac4j.core.exception.http.{
  BadRequestAction,
  ForbiddenAction,
  FoundAction,
  HttpAction,
  NoContentAction,
  OkAction,
  SeeOtherAction,
  TemporaryRedirectAction,
  UnauthorizedAction
}

import scala.concurrent.Future

object AkkaHttpActionAdapter extends HttpActionAdapter[Future[RouteResult], AkkaHttpWebContext] {
  override def adapt(action: HttpAction, context: AkkaHttpWebContext): Future[Complete] = {
    Future.successful(Complete(action match {
      case _: UnauthorizedAction =>
        // XHR requests don't receive a TEMP_REDIRECT but a UNAUTHORIZED. The client can handle this
        // to trigger the proper redirect anyway, but for a correct flow the session cookie must be set
        context.addResponseSessionCookie()
        HttpResponse(Unauthorized)
      case _: BadRequestAction =>
        HttpResponse(BadRequest)
      case _ if action.getCode == HttpConstants.CREATED =>
        HttpResponse(Created)
      case _: ForbiddenAction =>
        HttpResponse(Forbidden)
      case a: FoundAction =>
        context.addResponseSessionCookie()
        HttpResponse(SeeOther, headers = List[HttpHeader](Location(Uri(a.getLocation))))
      case a: SeeOtherAction =>
        context.addResponseSessionCookie()
        HttpResponse(SeeOther, headers = List[HttpHeader](Location(Uri(a.getLocation))))
      case a: OkAction =>
        val contentBytes = a.getContent.getBytes
        val entity = context.getContentType.map(ct => HttpEntity(ct, contentBytes)).getOrElse(HttpEntity(contentBytes))
        HttpResponse(OK, entity = entity)
      case _: NoContentAction =>
        HttpResponse(NoContent)
      case _ if action.getCode == 500 =>
        HttpResponse(InternalServerError)
      case _ =>
        HttpResponse(StatusCodes.getForKey(action.getCode).getOrElse(custom(action.getCode, "")))
    }))
  }
} 
Example 41
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 42
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 43
Source File: ValidationDirectivesSpec.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.pattern.validation

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.directives.MethodDirectives
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.{FunSpecLike, Matchers}
import org.squbs.pattern.validation.ValidationDirectives.{validate => _}
import spray.json.{DefaultJsonProtocol, RootJsonFormat}

object MyJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val PersonFormat: RootJsonFormat[Person] = jsonFormat4(Person)
}

class ValidationDirectivesSpec extends FunSpecLike with Matchers with ScalatestRouteTest{

  val ValidationPassed = "Validation Passed"

  import MyJsonProtocol._
  import org.squbs.pattern.validation.SampleValidators._

  val route: Route =
    (path("person") & MethodDirectives.post) {
      entity(as[Person]) { person =>
        import ValidationDirectives._
        validate(person) {
          complete(ValidationPassed)
        }
      }
    }

  describe("ValidationDirectives") {

    it(s"should return [$ValidationPassed] string with 200 for a valid content without middle name") {
      Post("/person", Person("John", "Smith", age = 25)) ~> route ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual ValidationPassed
      }
    }

    it(s"should return [$ValidationPassed] string with 200 for a valid content with middle name") {
      Post("/person", Person("John", "Smith", Some("Mike"), age = 25)) ~> route ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual ValidationPassed
      }
    }

    it("should reject with Last Name") {
      Post("/person", Person("John", "", age = 25)) ~> route ~> check {
        rejections shouldEqual List(ValidationRejection("Last Name"))
      }
    }

    it("should reject with middleName") {
      Post("/person", Person("John", "Smith", Some(""), age = 25)) ~> route ~> check {
        rejections shouldEqual List(ValidationRejection("middleName"))
      }
    }

    it("should reject with Last Name, middleName, age") {
      Post("/person", Person("John", "", Some(""), age = -1)) ~> route ~> check {
        rejections shouldEqual List(ValidationRejection("Last Name, middleName, age"))
      }
    }
  }

} 
Example 44
Source File: VinylDNSRouteTestHelper.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives.{complete, extractUnmatchedPath}
import akka.http.scaladsl.server.{MalformedRequestContentRejection, RejectionHandler}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.json4s.MappingException

trait VinylDNSRouteTestHelper { this: ScalatestRouteTest =>
  import scala.concurrent.duration._
  import akka.http.scaladsl.testkit.RouteTestTimeout

  implicit val testTimeout = RouteTestTimeout(10.seconds)

  implicit def validationRejectionHandler: RejectionHandler =
    RejectionHandler
      .newBuilder()
      .handle {
        case MalformedRequestContentRejection(msg, MappingException(_, _)) =>
          complete(
            HttpResponse(
              status = StatusCodes.BadRequest,
              entity = HttpEntity(ContentTypes.`application/json`, msg)
            )
          )
      }
      .handleNotFound {
        extractUnmatchedPath { p =>
          complete((StatusCodes.NotFound, s"The requested path [$p] does not exist."))
        }
      }
      .result()
} 
Example 45
Source File: ConfigurableInitTimeActor.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.unicomplex.timeout

import akka.NotUsed
import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes}
import akka.stream.scaladsl.Flow
import org.slf4j.LoggerFactory
import org.squbs.unicomplex.FlowDefinition

object ConfigurableInitTimeActor {
  def log = LoggerFactory.getLogger(classOf[ConfigurableInitTimeActor])
}

class ConfigurableInitTimeActor extends FlowDefinition {
  import ConfigurableInitTimeActor.log

  override def flow: Flow[HttpRequest, HttpResponse, NotUsed] = {
    val system = this.context.system

    val initTime = Option(system.settings.config.getDuration("squbs.test.actor-init-time"))
      .get

    log.info(s"I'll be ready to go in $initTime")
    Thread.sleep(initTime.toMillis)
    log.info("Ready to work!")

    Flow[HttpRequest].map { r => HttpResponse(StatusCodes.OK, entity = "Hello") }
  }
} 
Example 46
Source File: UnicomplexTimeoutSpec.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.model.StatusCodes
import akka.stream.ActorMaterializer
import akka.testkit.{ImplicitSender, TestKit}
import com.typesafe.config.ConfigFactory
import org.scalatest._
import org.scalatest.concurrent.Waiters
import org.squbs.lifecycle.GracefulStop
import org.squbs.unicomplex.Timeouts._

import scala.concurrent.Await

object UnicomplexTimeoutSpec {

  val dummyJarsDir = getClass.getClassLoader.getResource("classpaths").getPath

  val classPaths = Array(
    "DummySvcActor"
  ) map (dummyJarsDir + "/" + _)

  val aConfig = ConfigFactory.parseString(
    s"""
       |squbs {
       |  actorsystem-name = UnicomplexTimeoutSpec
       |  ${JMX.prefixConfig} = true
       |}
       |default-listener {
       |  bind-port = 0
       |}
       |akka.http.server {
       |  request-timeout = 3s
       |}
     """.stripMargin)

  val boot = UnicomplexBoot(aConfig)
    .createUsing {(name, config) => ActorSystem(name, config)}
    .scanComponents(classPaths)
    .initExtensions.start()

}

class UnicomplexTimeoutSpec extends TestKit(UnicomplexTimeoutSpec.boot.actorSystem) with ImplicitSender
    with WordSpecLike with Matchers with BeforeAndAfterAll with Waiters {

  implicit val am = ActorMaterializer()
  import akka.pattern.ask
  val port = Await.result((Unicomplex(system).uniActor ? PortBindings).mapTo[Map[String, Int]], awaitMax)("default-listener")

  override def afterAll(): Unit = {
    Unicomplex(system).uniActor ! GracefulStop
  }

  "Unicomplex" must {

    "Cause a timeout event" in {
      system.settings.config getString "akka.http.server.request-timeout" should be ("3s")
      val response = Await.result(get(s"http://127.0.0.1:$port/dummysvcactor/timeout"), awaitMax)
      // TODO This test is useless to me..  Need to explore how we can intervene with timeouts..  Do we need to ?
      // There may be scenarios, where we may want to do some work when a timeout happens..  So, having a hook
      // would be useful..
      response.status should be (StatusCodes.ServiceUnavailable)
    }
  }
} 
Example 47
Source File: CorsServer.scala    From akka-http-cors   with Apache License 2.0 5 votes vote down vote up
package ch.megard.akka.http.cors.scaladsl

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server._


object CorsServer extends HttpApp {
  def main(args: Array[String]): Unit = {
    CorsServer.startServer("127.0.0.1", 9000)
  }

  protected def routes: Route = {
    import CorsDirectives._

    // Your CORS settings are loaded from `application.conf`

    // Your rejection handler
    val rejectionHandler = corsRejectionHandler.withFallback(RejectionHandler.default)

    // Your exception handler
    val exceptionHandler = ExceptionHandler {
      case e: NoSuchElementException => complete(StatusCodes.NotFound -> e.getMessage)
    }

    // Combining the two handlers only for convenience
    val handleErrors = handleRejections(rejectionHandler) & handleExceptions(exceptionHandler)

    // Note how rejections and exceptions are handled *before* the CORS directive (in the inner route).
    // This is required to have the correct CORS headers in the response even when an error occurs.
    // format: off
    handleErrors {
      cors() {
        handleErrors {
          path("ping") {
            complete("pong")
          } ~
          path("pong") {
            failWith(new NoSuchElementException("pong not found, try with ping"))
          }
        }
      }
    }
    // format: on
  }
} 
Example 48
Source File: AkkaKubernetesSpec.scala    From akka-kubernetes-tests   with Apache License 2.0 5 votes vote down vote up
package akka.kubernetes.sample

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.management.cluster.{ClusterHttpManagementJsonProtocol, ClusterMembers}
import akka.stream.ActorMaterializer
import org.scalatest.concurrent.{Eventually, ScalaFutures}
import org.scalatest.time.{Seconds, Span}
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpec}

class AkkaKubernetesSpec extends WordSpec with BeforeAndAfterAll with ScalaFutures with Matchers with ClusterHttpManagementJsonProtocol with Eventually {
  implicit val system = ActorSystem()
  implicit val materializer = ActorMaterializer()

  implicit override val patienceConfig = PatienceConfig(timeout = Span(60, Seconds), interval = Span(2, Seconds))

  val target = system.settings.config.getString("akka.k8s.target")
  val clusterSize = system.settings.config.getInt("akka.k8s.cluster-size")
  val deployedVersion = system.settings.config.getString("akka.k8s.deployment-version")

  val log = system.log

  log.info("Running with target {} clusterSize {} version {}", target, clusterSize, deployedVersion)

  "Version deployed" should {
    "should have been updated" in {
      eventually {
        val response = Http().singleRequest(HttpRequest(uri = s"$target/version")).futureValue
        val reportedVersion = Unmarshal(response.entity).to[String].futureValue
        log.info("Reported version is: {}", reportedVersion)
        reportedVersion shouldEqual deployedVersion
      }
    }
  }

  "Cluster formation" should {

    "work" in {
      eventually {
        val response = Http().singleRequest(HttpRequest(uri = s"$target/cluster/members")).futureValue
        response.status shouldEqual StatusCodes.OK

        val clusterMembers: ClusterMembers = Unmarshal(response).to[ClusterMembers].futureValue
        withClue("Latest response: " + clusterMembers) {
          clusterMembers.members.size shouldEqual clusterSize
          clusterMembers.unreachable shouldEqual Seq.empty
        }
        log.info("Current cluster members: {}", clusterMembers)
      }
    }
  }

  "Akka Boss (singleton)" should {

    "say hello" in {
      val response = Http().singleRequest(HttpRequest(uri = s"$target/boss")).futureValue
      response.status shouldEqual StatusCodes.OK
    }
  }

  "Akka members (sharding)" should {
    "do some work" in {
      val response = Http().singleRequest(HttpRequest(uri = s"$target/team-member/johan")).futureValue
      response.status shouldEqual StatusCodes.OK
    }
  }

  override protected def afterAll(): Unit = {
    system.terminate()
  }
} 
Example 49
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 50
Source File: ClusterSoakSpec.scala    From akka-kubernetes-tests   with Apache License 2.0 5 votes vote down vote up
package akka.cluster.soak
import akka.actor.ActorSystem
import akka.discovery.ServiceDiscovery.Resolved
import akka.event.Logging
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.kubernetes.soak.Tests.{ResponseTimeNanos, Target}
import akka.kubernetes.soak.{StatsJsonSupport, TestResults}
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.{Seconds, Span}
import org.scalatest.{Matchers, WordSpec}
import akka.util.PrettyDuration._

import scala.collection.immutable
import scala.concurrent.Future
import scala.concurrent.duration._

class ClusterSoakSpec(endpoints: Resolved)(implicit system: ActorSystem)
    extends WordSpec
    with StatsJsonSupport
    with ScalaFutures
    with Matchers {

  import system.dispatcher
  implicit val mat = ActorMaterializer()
  implicit override val patienceConfig = PatienceConfig(timeout = Span(30, Seconds), interval = Span(2, Seconds))
  val log = Logging(system, getClass)

  "The Clustered service" should {

    "not have had any failures" in {

      val responses: immutable.Seq[TestResults] = Source(endpoints.addresses)
        .mapAsyncUnordered(10) { rt =>
          log.info("Hitting {}", rt.host)
          val request = HttpRequest(uri = s"http://${rt.host}:${rt.port.getOrElse(8080)}/stats")
          for {
            response <- Http().singleRequest(request)
            entity <- response.entity.toStrict(1.second)
            results <- response.status match {
              case StatusCodes.OK =>
                Unmarshal(entity).to[TestResults]
              case unexpected =>
                Future.failed(
                  new RuntimeException(s"Unexpected response code: $unexpected body: ${entity.data.utf8String}")
                )
            }
          } yield results
        }
        .runWith(Sink.seq)
        .futureValue

      log.info("{} nodes tested", responses.size)

      val maxJoinTimes =
        responses.map(_.joiningTime).sorted.reverse.take(5).map(_.nanos.pretty)

      log.info("Max join times: {}", maxJoinTimes)

      val maxResponseTimePerNode: immutable.Seq[(Target, ResponseTimeNanos)] =
        responses.map(_.lastResult.responses.maxBy(_._2))

      val averageResponseTimesPerNode = responses
        .map((eachNode: TestResults) => {
          val total = eachNode.lastResult.responses.map(_._2).sum.nanos
          val count = eachNode.lastResult.responses.size
          total / count
        })
        .sorted
        .reverse

      log.info("All response times: {}", responses)
      log.info("Slowest response times across all node pings: {}",
               maxResponseTimePerNode.sortBy(_._2).reverse.take(5).map(_._2.nanos.pretty))
      log.info("Slowest average response times across all node pings: {}",
               averageResponseTimesPerNode.take(5).map(_.pretty))

      responses.filter(_.testsFailed != 0) shouldEqual Nil

      withClue("Response took longer than 2 seconds. Do some investigation") {
        responses.filter(_.lastResult.responses.exists(_._2.nanos > 2.seconds)) shouldEqual Nil
      }

      withClue("Found unreachable events") {
        responses.filter(_.memberUnreachableEvents != 0) shouldEqual Nil
      }

      withClue("Found downed events") {
        responses.filter(_.memberDownedEvents != 0) shouldEqual Nil
      }
    }
  }

} 
Example 51
Source File: BaseEndpoints.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.japi.Util._
import com.github.vonnagy.service.container.http.directives.CIDRDirectives
import com.github.vonnagy.service.container.http.routing.RoutedEndpoints
import com.github.vonnagy.service.container.service.ServicesManager.ShutdownService
import org.joda.time.{DateTime, DateTimeZone}

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

class BaseEndpoints(implicit system: ActorSystem, executor: ExecutionContext)
  extends RoutedEndpoints with CIDRDirectives {

  lazy val config = system.settings.config.getConfig("container.http")
  lazy val serviceActor = system.actorSelection("/user/service")

  implicit val marshaller = plainMarshaller

  val route = {
    path("favicon.ico") {
      complete(StatusCodes.NoContent)
    } ~
      path("ping") {
        complete("pong: ".concat(new DateTime(System.currentTimeMillis(), DateTimeZone.UTC).toString))
      } ~
      path("shutdown") {
        post {
          cidrFilter(immutableSeq(config.getStringList("cidr.allow")),
            immutableSeq(config.getStringList("cidr.deny"))) { ctx =>

            ctx.complete("The system is being shutdown: ".concat(new DateTime(System.currentTimeMillis(),
              DateTimeZone.UTC).toString)) andThen {
              case _ =>
                // Send a message to the root actor of this service
                serviceActor.resolveOne()(3 seconds).onComplete {
                  case Success(ref) => ref ! ShutdownService(true)
                  case Failure(_) => sys.exit()
                }
            }
          }
        }
      }
  }
} 
Example 52
Source File: HealthEndpoints.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.health

import akka.actor.ActorSystem
import akka.http.scaladsl.marshalling._
import akka.http.scaladsl.model.{MediaTypes, StatusCodes}
import akka.http.scaladsl.server._
import akka.japi.Util.immutableSeq
import com.github.vonnagy.service.container.http.DefaultMarshallers
import com.github.vonnagy.service.container.http.directives.CIDRDirectives
import com.github.vonnagy.service.container.http.routing.RoutedEndpoints
import org.joda.time.DateTime

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



  def handleHealth[T <: ContainerHealth](loadBalancer: Boolean)(implicit marshaller: ToEntityMarshaller[AnyRef]):
  PartialFunction[Try[ContainerHealth], Route] = {

    case Success(check) =>
      check.state match {
        case HealthState.OK => complete(serialize(loadBalancer, check))
        case HealthState.DEGRADED => complete(serialize(loadBalancer, check))
        case HealthState.CRITICAL =>
          complete(StatusCodes.ServiceUnavailable -> serialize(loadBalancer, check))
      }

    case Failure(t) =>
      log.error("An error occurred while fetching the system's health", t)
      complete(StatusCodes.InternalServerError, ContainerHealth(ContainerInfo.host, ContainerInfo.application,
        ContainerInfo.applicationVersion, ContainerInfo.containerVersion,
        DateTime.now, HealthState.CRITICAL, t.getMessage, Nil))
  }

} 
Example 53
Source File: MetricsEndpointsSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.metrics

import java.net.InetAddress

import akka.http.scaladsl.model.headers.{Accept, `Remote-Address`}
import akka.http.scaladsl.model.{ContentTypes, MediaTypes, RemoteAddress, StatusCodes}
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.routing.Rejection.NotFoundRejection
import org.specs2.mutable.Specification

class MetricsEndpointsSpec extends Specification with Specs2RouteTest {

  val endpoints = new MetricsEndpoints()(system, system.dispatcher)

  def remoteAddress(ip: String) = RemoteAddress(InetAddress.getByName(ip))

  "The routing infrastructure should support" should {

    "a call to /metrics to be handled" in {
      Get("/metrics").withHeaders(`Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        contentType === ContentTypes.`application/json`
        status must be equalTo (StatusCodes.OK)
      }
    }

    "a call to /metrics should return json" in {
      Get("/metrics").withHeaders(Accept(MediaTypes.`application/json`),
        `Remote-Address`(remoteAddress("127.0.0.1"))) ~> endpoints.route ~> check {
        handled must beTrue
        contentType === ContentTypes.`application/json`
      }
    }

    "a call to /metrics should return an error due to CIDR rules" in {
      Get("/metrics").withHeaders(Accept(MediaTypes.`application/json`),
        `Remote-Address`(remoteAddress("192.168.1.1"))) ~> endpoints.route ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }
  }

} 
Example 54
Source File: CIDRDirectivesSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http.directives

import java.net.InetAddress

import akka.http.scaladsl.model.headers._
import akka.http.scaladsl.model.{RemoteAddress, StatusCodes}
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.routing.Rejection.NotFoundRejection
import org.specs2.mutable.Specification


class CIDRDirectivesSpec extends Specification with CIDRDirectives with Specs2RouteTest {

  val yeah = complete("Yeah!")

  def remoteAddress(ip: String) = RemoteAddress(InetAddress.getByName(ip))

  "CIDRDirectives" should {

    "allow call when no allows or denies" in {
      Get() ~> addHeaders(`Remote-Address`(remoteAddress("192.168.1.1"))) ~> {
        cidrFilter(Seq(), Seq()) {
          yeah
        }
      } ~> check {
        handled === true
        status === StatusCodes.OK
      }
    }

    "allow call when no denies, but matches allow" in {
      Get() ~> addHeaders(`Remote-Address`(remoteAddress("192.168.1.1"))) ~> {
        cidrFilter(Seq("192.168.1.1/1"), Seq()) {
          yeah
        }
      } ~> check {
        handled === true
        status === StatusCodes.OK
      }
    }

    "allow call when does not match deny, but matches allow" in {
      Get() ~> addHeaders(`Remote-Address`(remoteAddress("192.168.1.1"))) ~> {
        cidrFilter(Seq("192.168.1.1/1"), Seq("10.0.0.1/1")) {
          yeah
        }
      } ~> check {
        handled === true
        status === StatusCodes.OK
      }
    }

    "disallow call when no denies and does not match allow" in {
      Get() ~> addHeaders(`Remote-Address`(remoteAddress("192.168.1.1"))) ~> {
        cidrFilter(Seq("127.0.0.1/1"), Seq()) {
          yeah
        }
      } ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }

    "disallow call when matches a deny" in {
      Get() ~> addHeaders(`Remote-Address`(remoteAddress("10.0.0.1"))) ~> {
        cidrFilter(Seq("192.168.1.1/1"), Seq("10.0.0.1/1")) {
          yeah
        }
      } ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }

    "disallow because there is no remote address header that has been injected" in {
      Get() ~> {
        cidrFilter(Seq(), Seq()) {
          yeah
        }
      } ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }
  }
} 
Example 55
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 56
Source File: BaseEndpointsSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.http

import java.net.InetAddress

import akka.http.scaladsl.model.headers.`Remote-Address`
import akka.http.scaladsl.model.{RemoteAddress, StatusCodes}
import akka.http.scaladsl.server.Directives
import com.github.vonnagy.service.container.Specs2RouteTest
import com.github.vonnagy.service.container.http.routing.Rejection.NotFoundRejection
import org.specs2.mutable.Specification

class BaseEndpointsSpec extends Specification with Directives with Specs2RouteTest {

  val endpoints = new BaseEndpoints

  "The base routing infrastructure" should {

    "return no content for favicon.ico" in {
      Get("/favicon.ico") ~> endpoints.route ~> check {
        status must be equalTo StatusCodes.NoContent
      }
    }

    "support a call to ping" in {
      Get("/ping") ~> endpoints.route ~> check {
        responseAs[String] must startWith("pong")
        status must beEqualTo(StatusCodes.OK)
      }
    }

    "a call to shutdown should return and error due to CIDR rules" in {
      Post("/shutdown").withHeaders(`Remote-Address`(RemoteAddress(InetAddress.getByName("192.168.1.1")))) ~> endpoints.route ~> check {
        handled must beFalse
        rejections.size must beEqualTo(1)
        rejections.head must be equalTo(NotFoundRejection("The requested resource could not be found"))
      }
    }

  }

} 
Example 57
Source File: ContainerServiceSpec.scala    From service-container   with Apache License 2.0 5 votes vote down vote up
package com.github.vonnagy.service.container.service

import akka.actor.{ActorSystem, Terminated}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import com.github.vonnagy.service.container.{AkkaTestkitSpecs2Support, TestUtils}
import com.typesafe.config.ConfigFactory
import org.specs2.concurrent.ExecutionEnv
import org.specs2.matcher.FutureMatchers
import org.specs2.mutable.SpecificationLike

class ContainerServiceSpec extends AkkaTestkitSpecs2Support(ActorSystem("test", {
  val http = TestUtils.temporaryServerHostnameAndPort()

  ConfigFactory.parseString(
  s"""
      container.http.interface="${http._2}"
      container.http.port=${http._3}
    """)})) with SpecificationLike with FutureMatchers {

  sequential
  val cont = new ContainerService(Nil, Nil, name = "test")

  "The ContainerService" should {

    "create the appropriate parts during construction" in {
      cont.registeredHealthChecks must be equalTo Nil
      cont.registeredRoutes must be equalTo Nil
      cont.started must beFalse
    }

    "start properly and respond to a `/ping` request" in {
      cont.start()
      cont.started must beTrue

      val host = system.settings.config.getString("container.http.interface")
      val port = system.settings.config.getInt("container.http.port")

      val resp = Http().singleRequest(HttpRequest(uri = s"http://$host:$port/ping"))
      resp.value.get.get.status must eventually(be_==(StatusCodes.OK))

    }

    "shut down properly when asked" in {
      cont.shutdown
      implicit val ec = ExecutionEnv.fromExecutionContext(system.dispatcher)
      cont.system.whenTerminated must beAnInstanceOf[Terminated].await
    }
  }
} 
Example 58
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 59
Source File: HttpCodec.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.http.json

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes.`application/json`
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.ExceptionHandler
import akka.http.scaladsl.unmarshalling.{FromEntityUnmarshaller, Unmarshaller}
import com.daml.util.ExceptionOps._
import scalaz.std.stream.unfold
import scalaz.{@@, Tag}
import spray.json._

import scala.concurrent.{ExecutionContext, Future}


object HttpCodec {
  sealed trait JsonApi
  val JsonApi = Tag.of[JsonApi]

  implicit val jsonExceptionHandler: ExceptionHandler = ExceptionHandler {
    case e: DeserializationException =>
      complete(
        (
          StatusCodes.BadRequest,
          ResponseFormats.errorsJsObject(
            StatusCodes.BadRequest,
            s"JSON parser error: ${e.msg}" +: unfoldCauses(e.cause).map(_.description): _*)))
  }

  private[this] def unfoldCauses(t: Throwable): Seq[Throwable] =
    unfold(t)(tnq => Option(tnq) map (tnn => (tnn, tnn.getCause)))

  private[this] val simpleJsValueUnmarshaller =
    Unmarshaller[String, JsValue] { implicit ec: ExecutionContext => value =>
      Future(value.parseJson)
    }

  implicit val jsValueUnmarshaller: FromEntityUnmarshaller[JsValue] =
    (implicitly[FromEntityUnmarshaller[String]] andThen simpleJsValueUnmarshaller
      forContentTypes `application/json`)

  implicit val jsValueMarshaller: ToEntityMarshaller[JsValue] =
    Marshaller.combined((_: JsValue).compactPrint)(Marshaller.stringMarshaller(`application/json`))

  implicit def jsonCodecUnmarshaller[A: RootJsonReader]: FromEntityUnmarshaller[A @@ JsonApi] =
    JsonApi.subst[FromEntityUnmarshaller, A](jsValueUnmarshaller map (_.convertTo[A]))

  implicit def jsonCodecMarshaller[A: RootJsonWriter]: ToEntityMarshaller[A @@ JsonApi] =
    JsonApi.subst[ToEntityMarshaller, A](Marshaller.combined((_: A).toJson))
} 
Example 60
Source File: HttpServiceIntegrationTest.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.http

import java.io.File
import java.nio.file.Files

import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpMethods, HttpRequest, StatusCodes, Uri}
import com.daml.http.Statement.discard
import com.daml.http.util.TestUtil.writeToFile
import org.scalacheck.Gen
import org.scalatest.{Assertion, BeforeAndAfterAll}

import scala.concurrent.Future

class HttpServiceIntegrationTest extends AbstractHttpServiceIntegrationTest with BeforeAndAfterAll {

  private val staticContent: String = "static"

  private val staticContentDir: File =
    Files.createTempDirectory("integration-test-static-content").toFile

  override def staticContentConfig: Option[StaticContentConfig] =
    Some(StaticContentConfig(prefix = staticContent, directory = staticContentDir))

  override def jdbcConfig: Option[JdbcConfig] = None

  private val expectedDummyContent: String = Gen
    .listOfN(100, Gen.identifier)
    .map(_.mkString(" "))
    .sample
    .getOrElse(throw new IllegalStateException(s"Cannot create dummy text content"))

  private val dummyFile: File =
    writeToFile(new File(staticContentDir, "dummy.txt"), expectedDummyContent).get
  require(dummyFile.exists)

  override protected def afterAll(): Unit = {
    // clean up temp directory
    discard { dummyFile.delete() }
    discard { staticContentDir.delete() }
    super.afterAll()
  }

  "should serve static content from configured directory" in withHttpService { (uri: Uri, _, _) =>
    Http()
      .singleRequest(
        HttpRequest(
          method = HttpMethods.GET,
          uri = uri.withPath(Uri.Path(s"/$staticContent/${dummyFile.getName}"))))
      .flatMap { resp =>
        discard { resp.status shouldBe StatusCodes.OK }
        val bodyF: Future[String] = getResponseDataBytes(resp, debug = false)
        bodyF.flatMap { body =>
          body shouldBe expectedDummyContent
        }
      }: Future[Assertion]
  }

  "Forwarded" - {
    import Endpoints.Forwarded
    "can 'parse' sample" in {
      Forwarded("for=192.168.0.1;proto=http;by=192.168.0.42").proto should ===(Some("http"))
    }

    "can 'parse' quoted sample" in {
      Forwarded("for=192.168.0.1;proto = \"https\" ;by=192.168.0.42").proto should ===(
        Some("https"))
    }
  }
} 
Example 61
Source File: TlsTest.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.http

import HttpServiceTestFixture.UseTls
import akka.http.scaladsl.model.{StatusCodes, Uri}
import org.scalatest.{Assertion, AsyncFreeSpec, Inside, Matchers}
import spray.json.{JsArray, JsObject}

import scala.concurrent.Future

@SuppressWarnings(Array("org.wartremover.warts.NonUnitStatements"))
class TlsTest
    extends AsyncFreeSpec
    with Matchers
    with Inside
    with AbstractHttpServiceIntegrationTestFuns {

  override def jdbcConfig = None

  override def staticContentConfig = None

  override def useTls = UseTls.Tls

  "connect normally with tls on" in withHttpService { (uri: Uri, _, _) =>
    getRequest(uri = uri.withPath(Uri.Path("/v1/query")))
      .flatMap {
        case (status, output) =>
          status shouldBe StatusCodes.OK
          assertStatus(output, StatusCodes.OK)
          inside(output) {
            case JsObject(fields) =>
              inside(fields.get("result")) {
                case Some(JsArray(vector)) => vector should have size 0L
              }
          }
      }: Future[Assertion]
  }
} 
Example 62
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 63
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 64
Source File: StatsDirectiveSpec.scala    From opencensus-scala   with Apache License 2.0 5 votes vote down vote up
package io.opencensus.scala.akka.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import io.opencensus.scala.http.testSuite.MockStats
import io.opencensus.scala.stats.{Distribution, MeasurementDouble}
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class StatsDirectiveSpec
    extends AnyFlatSpec
    with ScalatestRouteTest
    with Matchers {

  def statsDirectiveWithMock: (StatsDirective, MockStats) = {
    val mockStats = new MockStats
    val directive = new StatsDirective {
      override private[http] val stats = mockStats
    }
    (directive, mockStats)
  }

  def routeWithMock = {
    val (directive, mock) = statsDirectiveWithMock

    val route = directive.recordRequest("routeName") {
      complete(StatusCodes.OK)
    }

    (route, mock)
  }

  it should "register the correct view" in {
    val (route, mock) = routeWithMock

    Get("/foo") ~> route ~> check {
      status shouldBe StatusCodes.OK

      mock.registeredViews should have length 1

      val serverLatency = mock.registeredViews.head

      serverLatency.name shouldBe "opencensus.io/http/server/server_latency"
      serverLatency.measure.name shouldBe "opencensus.io/http/server/server_latency"
      serverLatency.aggregation shouldBe a[Distribution]
    }
  }

  it should "record the correct measure value" in {
    val (route, mock) = routeWithMock

    Get("/foo") ~> route ~> check {
      status shouldBe StatusCodes.OK

      mock.recordedMeasurements should have length 1

      val (measurement, _) = mock.recordedMeasurements.head

      measurement match {
        case MeasurementDouble(measure, value) =>
          measure.name shouldBe "opencensus.io/http/server/server_latency"
          value.toInt shouldBe >(0)
        case other => fail(s"Expected MeasurementDouble got $other")
      }
    }
  }

  it should "record the correct measure tags" in {
    val (route, mock) = routeWithMock

    Get("/foo") ~> route ~> check {
      status shouldBe StatusCodes.OK
      mock.recordedMeasurements should have length 1
      val (_, tags) = mock.recordedMeasurements.head

      val tagsKeyValues =
        tags.map(tag => (tag.key.getName, tag.value.asString()))

      val expectedTags = List(
        "http_server_method" -> "GET",
        "http_server_route"  -> "routeName",
        "http_server_status" -> "200"
      )

      tagsKeyValues should contain theSameElementsAs expectedTags
    }
  }
} 
Example 65
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 66
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 67
Source File: AuthRoute.scala    From matcher   with MIT License 5 votes vote down vote up
package com.wavesplatform.dex.api.routes

import akka.http.scaladsl.marshalling.{ToResponseMarshallable, ToResponseMarshaller}
import akka.http.scaladsl.model.{StatusCode, StatusCodes}
import akka.http.scaladsl.server.{Directive0, Directive1}
import com.wavesplatform.dex.api.http.entities.{MatcherResponse, SimpleErrorResponse}
import com.wavesplatform.dex.api.http.headers.{`X-Api-Key`, `X-User-Public-Key`, api_key}
import com.wavesplatform.dex.api.ws.routes.MatcherWebSocketRoute
import com.wavesplatform.dex.domain.account.PublicKey
import com.wavesplatform.dex.domain.crypto
import com.wavesplatform.dex.error.{ApiKeyIsNotProvided, ApiKeyIsNotValid, MatcherError, UserPublicKeyIsNotValid}

trait AuthRoute { this: ApiRoute =>

  protected val apiKeyHash: Option[Array[Byte]]

  def withAuth(implicit matcherResponseTrm: ToResponseMarshaller[MatcherResponse]): Directive0 = {

    def correctResponse(statusCode: StatusCode, matcherError: MatcherError): ToResponseMarshallable = this match {
      case _: MatcherWebSocketRoute => matcherError.toWsHttpResponse(statusCode)
      case _                        => SimpleErrorResponse(statusCode, matcherError)
    }
    apiKeyHash.fold[Directive0] { complete(SimpleErrorResponse(StatusCodes.InternalServerError, ApiKeyIsNotProvided)) } { hashFromSettings =>
      optionalHeaderValueByType[`X-Api-Key`](()).flatMap {
        case Some(key) if java.util.Arrays.equals(crypto secureHash key.value, hashFromSettings) => pass
        case _ =>
          optionalHeaderValueByType[api_key](()).flatMap {
            case Some(key) if java.util.Arrays.equals(crypto secureHash key.value, hashFromSettings) => pass
            case _                                                                                   => complete { correctResponse(StatusCodes.Forbidden, ApiKeyIsNotValid) }
          }
      }
    }
  }

  def withUserPublicKeyOpt(implicit matcherResponseTrm: ToResponseMarshaller[MatcherResponse]): Directive1[Option[PublicKey]] =
    optionalHeaderValueByType[`X-User-Public-Key`](()).flatMap {
      case None => provide(None)
      case Some(rawPublicKey) =>
        PublicKey.fromBase58String(rawPublicKey.value) match {
          case Left(_)  => complete(SimpleErrorResponse(StatusCodes.BadRequest, UserPublicKeyIsNotValid))
          case Right(x) => provide[Option[PublicKey]](Some(PublicKey(x)))
        }
    }
} 
Example 68
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 69
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 70
Source File: OrderBookHttpInfo.scala    From matcher   with MIT License 5 votes vote down vote up
package com.wavesplatform.dex.api.http

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import com.wavesplatform.dex.actors.OrderBookAskAdapter
import com.wavesplatform.dex.actors.orderbook.AggregatedOrderBookActor.Depth
import com.wavesplatform.dex.api.http.entities.MatcherResponse.toHttpResponse
import com.wavesplatform.dex.api.http.entities.{HttpMarketStatus, HttpOrderBook, OrderBookUnavailable, SimpleResponse}
import com.wavesplatform.dex.domain.asset.{Asset, AssetPair}
import com.wavesplatform.dex.model.MatcherModel.{DecimalsFormat, Denormalized}
import com.wavesplatform.dex.time.Time
import play.api.libs.json.Json

import scala.concurrent.{ExecutionContext, Future}

class OrderBookHttpInfo(settings: OrderBookHttpInfo.Settings, askAdapter: OrderBookAskAdapter, time: Time, assetDecimals: Asset => Option[Int])(
    implicit ec: ExecutionContext) {

  private val marketStatusNotFound = toHttpResponse(
    SimpleResponse(StatusCodes.NotFound, Json.obj("message" -> "There is no information about this asset pair"))
  )

  def getMarketStatus(assetPair: AssetPair): Future[HttpResponse] =
    askAdapter.getMarketStatus(assetPair).map {
      case Left(e) => toHttpResponse(OrderBookUnavailable(e))
      case Right(maybeMarketStatus) =>
        maybeMarketStatus match {
          case Some(ms) => toHttpResponse(SimpleResponse(HttpMarketStatus fromMarketStatus ms))
          case None     => marketStatusNotFound
        }
    }

  def getHttpView(assetPair: AssetPair, format: DecimalsFormat, depth: Option[Depth]): Future[HttpResponse] =
    askAdapter.getHttpView(assetPair, format, settings.nearestBigger(depth)).map {
      case Right(x) => x.getOrElse(getDefaultHttpView(assetPair, format))
      case Left(e)  => toHttpResponse(OrderBookUnavailable(e))
    }

  private def getDefaultHttpView(assetPair: AssetPair, format: DecimalsFormat): HttpResponse = {
    val entity = HttpOrderBook(time.correctedTime(), assetPair, Seq.empty, Seq.empty, assetPairDecimals(assetPair, format))
    HttpResponse(
      entity = HttpEntity(
        ContentTypes.`application/json`,
        HttpOrderBook.toJson(entity)
      )
    )
  }

  private def assetPairDecimals(assetPair: AssetPair, format: DecimalsFormat): Option[(Depth, Depth)] = format match {
    case Denormalized => assetDecimals(assetPair.amountAsset).zip(assetDecimals(assetPair.priceAsset)).headOption
    case _            => None
  }
}

object OrderBookHttpInfo {
  case class Settings(depthRanges: List[Int], defaultDepth: Option[Int]) {
    def nearestBigger(to: Option[Int]): Int =
      to.orElse(defaultDepth)
        .flatMap(desiredDepth => depthRanges.find(_ >= desiredDepth))
        .getOrElse(depthRanges.max)
  }
} 
Example 71
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 72
Source File: AuthRoute.scala    From akka-http-rest   with MIT License 5 votes vote down vote up
package me.archdev.restapi.http.routes

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.generic.auto._
import io.circe.syntax._
import me.archdev.restapi.core.auth.AuthService

import scala.concurrent.ExecutionContext

class AuthRoute(authService: AuthService)(implicit executionContext: ExecutionContext) extends FailFastCirceSupport {

  import StatusCodes._
  import authService._

  val route = pathPrefix("auth") {
    path("signIn") {
      pathEndOrSingleSlash {
        post {
          entity(as[LoginPassword]) { loginPassword =>
            complete(
              signIn(loginPassword.login, loginPassword.password).map {
                case Some(token) => OK         -> token.asJson
                case None        => BadRequest -> None.asJson
              }
            )
          }
        }
      }
    } ~
    path("signUp") {
      pathEndOrSingleSlash {
        post {
          entity(as[UsernamePasswordEmail]) { userEntity =>
            complete(Created -> signUp(userEntity.username, userEntity.email, userEntity.password))
          }
        }
      }
    }
  }

  private case class LoginPassword(login: String, password: String)
  private case class UsernamePasswordEmail(username: String, email: String, password: String)

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

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport
import io.circe.generic.auto._
import io.circe.syntax._
import me.archdev.restapi.core.UserProfileUpdate
import me.archdev.restapi.core.profiles.UserProfileService
import me.archdev.restapi.utils.SecurityDirectives

import scala.concurrent.ExecutionContext

class ProfileRoute(
    secretKey: String,
    usersService: UserProfileService
)(implicit executionContext: ExecutionContext)
    extends FailFastCirceSupport {

  import SecurityDirectives._
  import StatusCodes._
  import usersService._

  val route = pathPrefix("profiles") {
    pathEndOrSingleSlash {
      get {
        complete(getProfiles().map(_.asJson))
      }
    } ~
    pathPrefix("me") {
      pathEndOrSingleSlash {
        authenticate(secretKey) { userId =>
          get {
            complete(getProfile(userId))
          } ~
          post {
            entity(as[UserProfileUpdate]) { userUpdate =>
              complete(updateProfile(userId, userUpdate).map(_.asJson))
            }
          }
        }
      }
    } ~
    pathPrefix(Segment) { id =>
      pathEndOrSingleSlash {
        get {
          complete(getProfile(id).map {
            case Some(profile) =>
              OK -> profile.asJson
            case None =>
              BadRequest -> None.asJson
          })
        } ~
        post {
          entity(as[UserProfileUpdate]) { userUpdate =>
            complete(updateProfile(id, userUpdate).map {
              case Some(profile) =>
                OK -> profile.asJson
              case None =>
                BadRequest -> None.asJson
            })
          }
        }
      }
    }
  }

} 
Example 74
Source File: LogCollectorRoutes.scala    From pulse   with Apache License 2.0 5 votes vote down vote up
package io.phdata.pulse.logcollector

import akka.http.scaladsl.common.EntityStreamingSupport
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity, StatusCodes }
import akka.http.scaladsl.server.Directives._
import com.typesafe.scalalogging.LazyLogging
import io.phdata.pulse.common.domain.{ LogEvent, TimeseriesRequest }


    post {
      // create a streaming Source from the incoming json string
      entity(as[TimeseriesRequest]) { eventRequest =>
        kuduService
          .map { client =>
            eventRequest.payload.map(event => client.save(eventRequest.table_name, List(event)))
          }
          .getOrElse(complete(StatusCodes.NotImplemented))

        complete(HttpEntity(ContentTypes.`application/json`, "ok"))
      }
    }
  }

} 
Example 75
Source File: ApiRoutesSpec.scala    From avoin-voitto   with MIT License 5 votes vote down vote up
package liigavoitto.api

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.stream.ActorMaterializer
import org.scalatest.{ Matchers, WordSpec }

class ApiRoutesSpec extends WordSpec with Matchers with ScalatestRouteTest with ApiRoutes {

  implicit val actorMaterializer: ActorMaterializer = ActorMaterializer()

  "SimpleRoute" should {
    "answer to GET requests to `/report/s24-123456`" in {
      Get("/report/s24-123456") ~> apiRoutes ~> check {
        status shouldBe StatusCodes.OK
      }
    }
    
    "handle reports in two languages" in {
      Get("/report/s24-123456?lang=sv") ~> apiRoutes ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] should include("lang: sv")
      }
    }
  }

  override val handler = new ApiHandler() {
    override def report(id: String, lang: String) = s"OK, $id. lang: $lang"
  }
} 
Example 76
Source File: BaseRoutesSpec.scala    From avoin-voitto   with MIT License 5 votes vote down vote up
package liigavoitto.api

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.{ Matchers, WordSpec }

class BaseRoutesSpec extends WordSpec with Matchers with ScalatestRouteTest {

  "BaseRoute" should {
    "answer to /ping request" in {
      Get("/ping") ~> BaseRoutes.baseRoutes ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "PONG"
      }
    }
  }

} 
Example 77
Source File: WebSocketClient.scala    From akka_streams_tutorial   with MIT License 5 votes vote down vote up
package sample.stream_actor

import akka.actor.{ActorRef, ActorSystem}
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.ws._
import akka.stream.scaladsl.{Flow, GraphDSL, Keep, Sink, Source}
import akka.stream.{FlowShape, SourceShape}
import sample.stream_actor.WindTurbineSimulator._

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

object WebSocketClient {
  def apply(id: String, endpoint: String, windTurbineSimulator: ActorRef)
           (implicit
            system: ActorSystem,
            executionContext: ExecutionContext) = {
    new WebSocketClient(id, endpoint, windTurbineSimulator)(system, executionContext)
  }
}

class WebSocketClient(id: String, endpoint: String, windTurbineSimulator: ActorRef)
                     (implicit
                      system: ActorSystem,
                      executionContext: ExecutionContext) {


  val webSocketFlow: Flow[Message, Message, Future[WebSocketUpgradeResponse]] = {
    val websocketUri = s"$endpoint/measurements/$id"
    Http().webSocketClientFlow(WebSocketRequest(websocketUri))
  }

  val outgoing = GraphDSL.create() { implicit builder =>
    val data = WindTurbineData(id)

    val flow = builder.add {
      Source.tick(1.second, 100.millis,())  //valve for the WindTurbineData frequency
        .map(_ => TextMessage(data.getNext))
    }

    SourceShape(flow.out)
  }

  val incoming = GraphDSL.create() { implicit builder =>
    val flow = builder.add {
      Flow[Message]
        .collect {
          case TextMessage.Strict(text) =>
            Future.successful(text)
          case TextMessage.Streamed(textStream) =>
            textStream.runFold("")(_ + _)
              .flatMap(Future.successful)
        }
        .mapAsync(1)(identity)
        .map(each => println(s"Client received msg: $each"))
    }

    FlowShape(flow.in, flow.out)
  }

  val (upgradeResponse, closed) = Source.fromGraph(outgoing)
    .viaMat(webSocketFlow)(Keep.right) // keep the materialized Future[WebSocketUpgradeResponse]
    .via(incoming)
    .toMat(Sink.ignore)(Keep.both) // also keep the Future[Done]
    .run()


  val connected =
    upgradeResponse.map { upgrade =>
      upgrade.response.status match {
        case StatusCodes.SwitchingProtocols => windTurbineSimulator ! Upgraded
        case statusCode => windTurbineSimulator ! FailedUpgrade(statusCode)
      }
    }

  connected.onComplete {
    case Success(_) => windTurbineSimulator ! Connected
    case Failure(ex) => windTurbineSimulator ! ConnectionFailure(ex)
  }

  closed.map { _ =>
    windTurbineSimulator ! Terminated
  }
  closed.onComplete {
    case Success(_)  => windTurbineSimulator ! Connected
    case Failure(ex) => windTurbineSimulator ! ConnectionFailure(ex)
  }
} 
Example 78
Source File: SidechainApiRejectionHandler.scala    From Sidechains-SDK   with MIT License 5 votes vote down vote up
package com.horizen.api.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.RejectionHandler
import akka.http.scaladsl.server._

object SidechainApiRejectionHandler {

  implicit val rejectionHandler = RejectionHandler.newBuilder()
    .handle {

      case ValidationRejection(msg, _) =>
        SidechainApiError(StatusCodes.BadRequest, "Validation failed").complete(msg)

      case MissingFormFieldRejection(fieldName) =>
        SidechainApiError(StatusCodes.BadRequest, "Missing Form Field").complete(s"The required ($fieldName) was not found.")

      case MissingQueryParamRejection(param) =>
        SidechainApiError(StatusCodes.BadRequest, "Missing Parameter").complete(s"The required ($param) was not found.")

      case MalformedQueryParamRejection(param, _, _) =>
        SidechainApiError(StatusCodes.BadRequest, "Malformed Parameter").complete(s"The required ($param) was not found.")

      case MalformedRequestContentRejection(msg, _) =>
        SidechainApiError(StatusCodes.BadRequest, "Malformed Request").complete(msg)

      case MethodRejection(_) =>
        SidechainApiError(StatusCodes.MethodNotAllowed, "HTTP method not allowed.")

      case RequestEntityExpectedRejection =>
        SidechainApiError(StatusCodes.BadRequest, "Request entity expected but not supplied")

    }
    .handleNotFound {
      SidechainApiError(StatusCodes.NotFound, "NotFound").complete("The requested resource could not be found.")
    }
    .result()
} 
Example 79
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 80
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 81
Source File: SidechainRejectionApiRouteTest.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._
import Directives._

class SidechainRejectionApiRouteTest extends SidechainApiRouteTest {

  override val basePath: String = "/wallet/"

  "The Api should to" should {

    "reply at /balance" in {
      Post(basePath + "balance") ~> (sidechainWalletApiRoute ~ walletBalanceApiRejected) ~> check {
        response shouldEqual ((Post(basePath + "balance") ~> sidechainWalletApiRoute).response)
      }
    }

    "reject and reply with http error" in {
      Post(basePath + "balance") ~> Route.seal({
        walletBalanceApiRejected ~ sidechainWalletApiRoute
      }) ~> check {
        status.intValue() shouldBe StatusCodes.NotFound.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
      }
      Post(basePath + "balance") ~> Route.seal({
        walletApiRejected ~ sidechainWalletApiRoute
      }) ~> check {
        status.intValue() shouldBe StatusCodes.NotFound.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
      }
      Post(basePath) ~> Route.seal({
        walletApiRejected ~ sidechainWalletApiRoute
      }) ~> check {
        status.intValue() shouldBe StatusCodes.NotFound.intValue
        responseEntity.getContentType() shouldEqual ContentTypes.`application/json`
      }
    }
  }
} 
Example 82
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 83
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 84
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 85
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 86
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 87
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 88
Source File: IngestionHandler.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.ingest.services

import akka.actor.SupervisorStrategy.Stop
import akka.actor.{Actor, ActorRef, OneForOneStrategy, ReceiveTimeout}
import akka.http.scaladsl.model.{StatusCode, StatusCodes}
import hydra.core.ingest.{HydraRequest, IngestionReport, RequestParams}
import hydra.ingest.services.IngestorRegistry.{
  FindAll,
  FindByName,
  LookupResult
}

import scala.concurrent.duration.FiniteDuration

trait IngestionHandler {
  this: Actor =>

  def timeout: FiniteDuration

  def request: HydraRequest

  //we require an actorref here for performance reasons
  def registry: ActorRef

  private val targetIngestor =
    request.metadataValue(RequestParams.HYDRA_INGESTOR_PARAM)

  targetIngestor match {
    case Some(ingestor) => registry ! FindByName(ingestor)
    case None           => registry ! FindAll
  }

  override def receive: Receive = {
    case LookupResult(Nil) =>
      val errorCode = targetIngestor
        .map(i =>
          StatusCodes
            .custom(404, s"No ingestor named $i was found in the registry.")
        )
        .getOrElse(StatusCodes.BadRequest)

      complete(errorWith(errorCode))

    case LookupResult(ingestors) =>
      context.actorOf(
        IngestionSupervisor.props(request, self, ingestors, timeout)
      )

    case report: IngestionReport =>
      complete(report)

  }

  override val supervisorStrategy =
    OneForOneStrategy() {
      case e: Exception =>
        fail(e)
        Stop
    }

  private def errorWith(statusCode: StatusCode) = {
    IngestionReport(request.correlationId, Map.empty, statusCode.intValue())
  }

  def complete(report: IngestionReport)

  def fail(e: Throwable)
} 
Example 89
Source File: HealthEndpointSpec.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.ingest.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.flatspec.AnyFlatSpecLike
import org.scalatest.matchers.should.Matchers

class HealthEndpointSpec
    extends Matchers
    with AnyFlatSpecLike
    with ScalatestRouteTest {

  "The HealthEndpoint" should "return a 200" in {
    Get("/health") ~> HealthEndpoint.route ~> check {
      status shouldEqual StatusCodes.OK
    }
  }
} 
Example 90
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 91
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 92
Source File: IngestorStatusSpec.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.core.protocol

import akka.http.scaladsl.model.StatusCodes
import org.scalatest.flatspec.AnyFlatSpecLike
import org.scalatest.matchers.should.Matchers

class IngestorStatusSpec extends Matchers with AnyFlatSpecLike {

  it should "return the right status codes" in {
    val ex = new IllegalArgumentException("")
    IngestorTimeout.statusCode.intValue shouldBe 408
    IngestorTimeout.completed shouldBe true
    IngestorJoined.statusCode.intValue shouldBe 202
    IngestorJoined.completed shouldBe false
    IngestorIgnored.statusCode.intValue shouldBe 406
    IngestorIgnored.completed shouldBe false
    RequestPublished.statusCode.intValue shouldBe 201
    RequestPublished.completed shouldBe false
    InvalidRequest(ex).statusCode.intValue shouldBe 400
    InvalidRequest(ex).completed shouldBe true
    IngestorError(ex).statusCode.intValue shouldBe 503
    IngestorError(ex).completed shouldBe true
    IngestorCompleted.statusCode.intValue shouldBe 200
    IngestorCompleted.completed shouldBe true
    IngestorCompleted.message shouldBe StatusCodes.OK.reason
  }

  it should "create an invalid request from a string" in {
    new InvalidRequest("error!").cause shouldBe a[IllegalArgumentException]
    new InvalidRequest("error!").cause.getMessage shouldBe "error!"
  }
} 
Example 93
Source File: HydraDirectivesSpec.scala    From hydra   with Apache License 2.0 5 votes vote down vote up
package hydra.core.http

import akka.http.scaladsl.model.headers.Location
import akka.http.scaladsl.model.{StatusCodes, Uri}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.matchers.should.Matchers
import org.scalatest.funspec.AnyFunSpecLike

class HydraDirectivesSpec
    extends Matchers
    with AnyFunSpecLike
    with ScalatestRouteTest
    with HydraDirectives {

  describe("Hydra Directives") {
    it("completes with location header") {
      Get() ~> completeWithLocationHeader(StatusCodes.OK, 123) ~> check {
        header[Location].get.uri shouldBe Uri("http://example.com/123")
      }
    }
    it("imperatively completes") {
      Get() ~> imperativelyComplete((ctx) => ctx.complete("DONE")) ~> check {
        responseAs[String] shouldBe "DONE"
      }
    }
  }

} 
Example 94
Source File: ClickhouseHostHealthTest.scala    From clickhouse-scala-client   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.crobox.clickhouse.balancing.discovery.health

import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.stream.scaladsl.{Sink, Source}
import com.crobox.clickhouse.ClickhouseClientSpec
import com.crobox.clickhouse.balancing.discovery.health.ClickhouseHostHealth.{Alive, Dead}
import com.crobox.clickhouse.internal.ClickhouseHostBuilder

import scala.util.{Failure, Success}

class ClickhouseHostHealthTest extends ClickhouseClientSpec {

  private val host = ClickhouseHostBuilder.toHost("localhost", Some(8123))
  it should "emit alive for ok response" in {
    Source
      .single((Success(HttpResponse(entity = "Ok.")), 0))
      .via(ClickhouseHostHealth.parsingFlow(host))
      .runWith(Sink.seq)
      .futureValue should contain theSameElementsAs Seq(Alive(host))
  }

  it should "emit dead for response with other status code" in {
    Source
      .single((Success(HttpResponse(status = StatusCodes.InternalServerError)), 0))
      .via(ClickhouseHostHealth.parsingFlow(host))
      .runWith(Sink.seq)
      .futureValue
      .toList match {
      case Dead(`host`, _) :: Nil => succeed
      case _                      => fail()
    }
  }

  it should "emit dead for failure" in {
    Source
      .single((Failure(new IllegalArgumentException), 0))
      .via(ClickhouseHostHealth.parsingFlow(host))
      .runWith(Sink.seq)
      .futureValue
      .toList match {
      case Dead(`host`, _) :: Nil => succeed
      case _                      => fail()
    }
  }

} 
Example 95
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 96
Source File: LoggerHandlerWithId.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.handler

import akka.http.scaladsl.model.{ StatusCode, StatusCodes }
import com.ing.wbaa.rokku.proxy.data.RequestId
import com.ing.wbaa.rokku.proxy.metrics.MetricsFactory
import com.ing.wbaa.rokku.proxy.metrics.MetricsFactory._
import com.typesafe.scalalogging.Logger
import org.slf4j.{ LoggerFactory, MDC }

import scala.collection.mutable

class LoggerHandlerWithId {

  @transient
  private lazy val log: Logger =
    Logger(LoggerFactory.getLogger(getClass.getName))

  private val requestIdKey = "request.id"
  private val statusCodeKey = "request.statusCode"

  def debug(message: String, args: Any*)(implicit id: RequestId): Unit = {
    MDC.put(requestIdKey, id.value)
    MDC.put(statusCodeKey, "-")
    log.debug(message, args.asInstanceOf[mutable.WrappedArray[AnyRef]]: _*)
    MDC.remove(requestIdKey)
    MDC.remove(statusCodeKey)
  }

  def info(message: String, args: Any*)(implicit id: RequestId): Unit = {
    MDC.put(requestIdKey, id.value)
    MDC.put(statusCodeKey, "-")
    log.info(message, args.asInstanceOf[mutable.WrappedArray[AnyRef]]: _*)
    MDC.remove(requestIdKey)
    MDC.remove(statusCodeKey)
  }

  def warn(message: String, args: Any*)(implicit id: RequestId, statusCode: StatusCode = StatusCodes.Continue): Unit = {
    MDC.put(requestIdKey, id.value)
    MDC.put(statusCodeKey, statusCode.value)
    if (args.isInstanceOf[mutable.WrappedArray[_]])
      log.warn(message, args.asInstanceOf[mutable.WrappedArray[AnyRef]]: _*)
    else
      log.warn(message, args.asInstanceOf[scala.collection.immutable.$colon$colon[AnyRef]]: _*)
    MDC.remove(requestIdKey)
    MDC.remove(statusCodeKey)
  }

  def error(message: String, args: Any*)(implicit id: RequestId, statusCode: StatusCode = StatusCodes.Continue): Unit = {
    MDC.put(requestIdKey, id.value)
    MDC.put(statusCodeKey, statusCode.value)
    countLogErrors(MetricsFactory.ERROR_REPORTED_TOTAL)
    if (args.isInstanceOf[mutable.WrappedArray[_]])
      log.error(message, args.asInstanceOf[mutable.WrappedArray[AnyRef]]: _*)
    else
      log.error(message, args.asInstanceOf[scala.collection.immutable.$colon$colon[AnyRef]]: _*)
    MDC.remove(requestIdKey)
    MDC.remove(statusCodeKey)
  }
} 
Example 97
Source File: AwsErrorCodes.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider.aws

import akka.http.scaladsl.model.{ StatusCode, StatusCodes }
import com.ing.wbaa.rokku.proxy.data.RequestId

import scala.xml.NodeSeq


object AwsErrorCodes {

  val errors: Map[StatusCode, (String, String)] =
    Map(
      StatusCodes.Forbidden -> (("AccessDenied", "Access Denied")),
      StatusCodes.InternalServerError -> (("InternalServerError", "Internal Server Error")),
      StatusCodes.Unauthorized -> (("Unauthorized", "Unauthorized")),
      StatusCodes.TooManyRequests -> (("TooManyRequests", "Too Many Requests")),
      StatusCodes.ServiceUnavailable -> (("Throttling", "SLOW DOWN")))

  def response(code: StatusCode, resource: String = "")(implicit requestId: RequestId = RequestId("")): NodeSeq = {
    val responseError = errors.getOrElse(code, ("Unexpected Error", "Unexpected Error"))
    <Error>
      <Code>{ responseError._1 }</Code>
      <Message>{ responseError._2 }</Message>
      <Resource>{ resource }</Resource>
      <RequestId>{ requestId.value }</RequestId>
    </Error>
  }
} 
Example 98
Source File: AuthenticationProviderSTS.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ HttpRequest, StatusCodes, Uri }
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import com.ing.wbaa.rokku.proxy.config.StsSettings
import com.ing.wbaa.rokku.proxy.data.{ AwsRequestCredential, JsonProtocols, RequestId, User, UserRawJson }
import com.ing.wbaa.rokku.proxy.handler.LoggerHandlerWithId
import com.ing.wbaa.rokku.proxy.util.JwtToken

import scala.concurrent.{ ExecutionContext, Future }

trait AuthenticationProviderSTS extends JsonProtocols with JwtToken {

  private val logger = new LoggerHandlerWithId

  import AuthenticationProviderSTS.STSException
  import spray.json._

  protected[this] implicit def system: ActorSystem
  protected[this] implicit def executionContext: ExecutionContext
  protected[this] implicit def materializer: Materializer

  protected[this] def stsSettings: StsSettings

  protected[this] def areCredentialsActive(awsRequestCredential: AwsRequestCredential)(implicit id: RequestId): Future[Option[User]] = {
    val QueryParameters =
      Map("accessKey" -> awsRequestCredential.accessKey.value) ++
        awsRequestCredential.sessionToken.map(s => "sessionToken" -> s.value)

    val uri = stsSettings.stsBaseUri
      .withPath(Uri.Path("/isCredentialActive"))
      .withQuery(Uri.Query(QueryParameters))

    Http()
      .singleRequest(
        HttpRequest(uri = uri)
          .addHeader(RawHeader("Authorization", createInternalToken))
          .addHeader(RawHeader("x-rokku-request-id", id.value))
      )
      .flatMap { response =>
        response.status match {

          case StatusCodes.OK =>
            Unmarshal(response.entity).to[String].map { jsonString =>
              Some(User(jsonString.parseJson.convertTo[UserRawJson]))
            }

          case StatusCodes.Forbidden =>
            logger.error(s"User not authenticated " +
              s"with accessKey (${awsRequestCredential.accessKey.value}) " +
              s"and sessionToken (${awsRequestCredential.sessionToken})")
            Future.successful(None)

          case c =>
            val msg = s"Received unexpected StatusCode ($c) for " +
              s"accessKey (${awsRequestCredential.accessKey.value}) " +
              s"and sessionToken (${awsRequestCredential.sessionToken})"
            logger.error(msg)
            Future.failed(STSException(msg))
        }
      }
  }
}

object AuthenticationProviderSTS {
  final case class STSException(private val message: String, private val cause: Throwable = None.orNull)
    extends Exception(message, cause)
} 
Example 99
Source File: MessageProviderKafka.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider

import akka.Done
import akka.http.scaladsl.model.{ HttpMethod, HttpMethods, StatusCodes }
import com.ing.wbaa.rokku.proxy.data.{ AWSMessageEventJsonSupport, RequestId, S3Request }
import com.ing.wbaa.rokku.proxy.handler.parsers.RequestParser.AWSRequestType
import com.ing.wbaa.rokku.proxy.provider.aws.{ s3ObjectCreated, s3ObjectRemoved }
import com.ing.wbaa.rokku.proxy.provider.kafka.EventProducer

import scala.concurrent.Future

trait MessageProviderKafka extends EventProducer with AWSMessageEventJsonSupport {

  def emitEvent(s3Request: S3Request, method: HttpMethod, principalId: String, awsRequest: AWSRequestType)(implicit id: RequestId): Future[Done] =
    method match {
      case HttpMethods.POST | HttpMethods.PUT =>
        prepareAWSMessage(s3Request, method, principalId, s3Request.userIps, s3ObjectCreated(method.value), id, StatusCodes.OK, awsRequest)
          .map(jse =>
            sendSingleMessage(jse.toString(), kafkaSettings.createEventsTopic, Some(method)))
          .getOrElse(Future(Done))

      case HttpMethods.DELETE =>
        prepareAWSMessage(s3Request, method, principalId, s3Request.userIps, s3ObjectRemoved(method.value), id, StatusCodes.OK, awsRequest)
          .map(jse =>
            sendSingleMessage(jse.toString(), kafkaSettings.deleteEventsTopic, Some(method)))
          .getOrElse(Future(Done))

      case _ => Future(Done)
    }

} 
Example 100
Source File: AuditLogProviderItTest.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider

import java.net.InetAddress

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{HttpMethods, HttpRequest, RemoteAddress, StatusCodes}
import com.ing.wbaa.rokku.proxy.config.KafkaSettings
import com.ing.wbaa.rokku.proxy.data._
import com.ing.wbaa.rokku.proxy.handler.parsers.RequestParser.RequestTypeUnknown
import net.manub.embeddedkafka.{EmbeddedKafka, EmbeddedKafkaConfig}
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AnyWordSpecLike

import scala.concurrent.ExecutionContext

class AuditLogProviderItTest extends AnyWordSpecLike with Diagrams with EmbeddedKafka with AuditLogProvider {

  implicit val testSystem: ActorSystem = ActorSystem("kafkaTest")

  private val testKafkaPort = 9093

  override def auditEnabled = true

  override implicit val kafkaSettings: KafkaSettings = new KafkaSettings(testSystem.settings.config) {
    override val bootstrapServers: String = s"localhost:$testKafkaPort"
  }

  override implicit val executionContext: ExecutionContext = testSystem.dispatcher

  implicit val requestId: RequestId = RequestId("test")

  val s3Request = S3Request(AwsRequestCredential(AwsAccessKey("a"), None), Some("demobucket"), Some("s3object"), Read())
    .copy(headerIPs = HeaderIPs(Some(RemoteAddress(InetAddress.getByName("127.0.0.1"))),
      Some(Seq(RemoteAddress(InetAddress.getByName("1.1.1.1")))),
      Some(RemoteAddress(InetAddress.getByName("2.2.2.2")))))

  "AuditLogProvider" should {
    "send audit" in {
      implicit val config = EmbeddedKafkaConfig(kafkaPort = testKafkaPort)

      withRunningKafka {
        Thread.sleep(3000)
        val createEventsTopic = "audit_events"
        createCustomTopic(createEventsTopic)
        auditLog(s3Request, HttpRequest(HttpMethods.PUT, "http://localhost", Nil), "testUser", RequestTypeUnknown(), StatusCodes.Processing)
        val result = consumeFirstStringMessageFrom(createEventsTopic)
        assert(result.contains("\"eventName\":\"PUT\""))
        assert(result.contains("\"sourceIPAddress\":\"ClientIp=unknown|X-Real-IP=127.0.0.1|X-Forwarded-For=1.1.1.1|Remote-Address=2.2.2.2\""))
        assert(result.contains("\"x-amz-request-id\":\"test\""))
        assert(result.contains("\"principalId\":\"testUser\""))
      }
    }
  }

} 
Example 101
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 102
Source File: AccessTokenSpec.scala    From akka-http-oauth2-client   with Apache License 2.0 5 votes vote down vote up
package com.github.dakatsuka.akka.http.oauth2.client

import akka.actor.ActorSystem
import akka.http.scaladsl.model.{ HttpEntity, HttpResponse, StatusCodes }
import akka.http.scaladsl.model.ContentTypes.`application/json`
import akka.stream.{ ActorMaterializer, Materializer }
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.{ Millis, Seconds, Span }
import org.scalatest.{ BeforeAndAfterAll, DiagrammedAssertions, FlatSpec }

import scala.concurrent.{ Await, ExecutionContext }
import scala.concurrent.duration.Duration

class AccessTokenSpec extends FlatSpec with DiagrammedAssertions with ScalaFutures with BeforeAndAfterAll {
  implicit val system: ActorSystem        = ActorSystem()
  implicit val ec: ExecutionContext       = system.dispatcher
  implicit val materializer: Materializer = ActorMaterializer()
  implicit val defaultPatience: PatienceConfig =
    PatienceConfig(timeout = Span(5, Seconds), interval = Span(700, Millis))

  override def afterAll(): Unit = {
    Await.ready(system.terminate(), Duration.Inf)
  }

  behavior of "AccessToken"

  it should "apply from HttpResponse" in {
    val accessToken  = "xxx"
    val tokenType    = "bearer"
    val expiresIn    = 86400
    val refreshToken = "yyy"

    val httpResponse = HttpResponse(
      status = StatusCodes.OK,
      headers = Nil,
      entity = HttpEntity(
        `application/json`,
        s"""
           |{
           |  "access_token": "$accessToken",
           |  "token_type": "$tokenType",
           |  "expires_in": $expiresIn,
           |  "refresh_token": "$refreshToken"
           |}
         """.stripMargin
      )
    )

    val result = AccessToken(httpResponse)

    whenReady(result) { token =>
      assert(token.accessToken == accessToken)
      assert(token.tokenType == tokenType)
      assert(token.expiresIn == expiresIn)
      assert(token.refreshToken.contains(refreshToken))
    }
  }
} 
Example 103
Source File: DropwizardMarshallersSpec.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.dropwizard.marshalling

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import fr.davit.akka.http.metrics.core.HttpMetricsRegistry.StatusGroupDimension
import fr.davit.akka.http.metrics.core.scaladsl.server.HttpMetricsDirectives._
import fr.davit.akka.http.metrics.dropwizard.DropwizardRegistry
import org.scalatest.BeforeAndAfterAll
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import spray.json.{DefaultJsonProtocol, JsValue}

import scala.concurrent.duration._

class DropwizardMarshallersSpec extends AnyFlatSpec with Matchers with ScalatestRouteTest with BeforeAndAfterAll {

  private case class JsonResponse(metrics: Map[String, JsValue])

  private trait Fixture extends SprayJsonSupport with DefaultJsonProtocol with DropwizardMarshallers {
    implicit val metricsFormat = jsonFormat1(JsonResponse)

    val registry = DropwizardRegistry()
    registry.underlying.counter("other.metric")
  }

  override def afterAll(): Unit = {
    cleanUp()
    super.afterAll()
  }

  "DropwizardMarshallers" should "expose metrics as json format" in new Fixture {
    // use metrics so they appear in the report
    val dimensions = Seq(StatusGroupDimension(StatusCodes.OK))
    registry.requests.inc()
    registry.receivedBytes.update(10)
    registry.active.inc()
    registry.responses.inc(dimensions)
    registry.errors.inc()
    registry.duration.observe(1.second, dimensions)
    registry.sentBytes.update(10)

    Get() ~> metrics(registry) ~> check {
      val json = responseAs[JsonResponse]
      // println(json)
      json.metrics.keys should contain theSameElementsAs Seq(
        "akka.http.requests.active",
        "akka.http.requests",
        "akka.http.requests.bytes",
        "akka.http.responses{status=2xx}",
        "akka.http.responses.errors",
        "akka.http.responses.duration{status=2xx}",
        "akka.http.responses.bytes",
        "other.metric"
      ).toSet
    }
  }

} 
Example 104
Source File: DropwizardRegistrySpec.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.dropwizard

import akka.http.scaladsl.model.StatusCodes
import fr.davit.akka.http.metrics.core.Dimension
import fr.davit.akka.http.metrics.core.HttpMetricsRegistry.{PathDimension, StatusGroupDimension}
import io.dropwizard.metrics5.MetricName
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.concurrent.duration._

import scala.collection.JavaConverters._

class DropwizardRegistrySpec extends AnyFlatSpec with Matchers {

  val dimensions = Seq(StatusGroupDimension(StatusCodes.OK), PathDimension("/api"))

  trait Fixture {
    val registry = DropwizardRegistry()

    def underlyingCounter(name: String, dims: Seq[Dimension] = Seq.empty): Long = {
      registry.underlying.getCounters.asScala(metricName(name, dims)).getCount
    }

    def underlyingHistogram(name: String, dims: Seq[Dimension] = Seq.empty): Long = {
      registry.underlying.getHistograms.asScala(metricName(name, dims)).getSum
    }

    def underlyingTimer(name: String, dims: Seq[Dimension] = Seq.empty): Long = {
      registry.underlying.getTimers.asScala(metricName(name, dims)).getSum
    }

    private def metricName(name: String, dims: Seq[Dimension]): MetricName = {
      MetricName.build(name).tagged(dims.map(d => d.key -> d.value).toMap.asJava)
    }
  }

  "DropwizardRegistry" should "set active metrics in the underlying registry" in new Fixture {
    registry.active.inc()
    underlyingCounter("akka.http.requests.active") shouldBe 1L
  }

  it should "set requests metrics in the underlying registry" in new Fixture {
    registry.requests.inc()
    underlyingCounter("akka.http.requests") shouldBe 1L
  }

  it should "set receivedBytes metrics in the underlying registry" in new Fixture {
    registry.receivedBytes.update(3)
    underlyingHistogram("akka.http.requests.bytes") shouldBe 3L
  }

  it should "set responses metrics in the underlying registry" in new Fixture {
    registry.responses.inc()
    underlyingCounter("akka.http.responses") shouldBe 1L

    registry.responses.inc(dimensions)
    underlyingCounter("akka.http.responses", dimensions) shouldBe 1L
  }

  it should "set errors metrics in the underlying registry" in new Fixture {
    registry.errors.inc()
    underlyingCounter("akka.http.responses.errors") shouldBe 1L

    registry.errors.inc(dimensions)
    underlyingCounter("akka.http.responses.errors", dimensions) shouldBe 1L
  }

  it should "set duration metrics in the underlying registry" in new Fixture {
    registry.duration.observe(3.seconds)
    underlyingTimer("akka.http.responses.duration") shouldBe 3000000000L

    registry.duration.observe(3.seconds, dimensions)
    underlyingTimer("akka.http.responses.duration", dimensions) shouldBe 3000000000L
  }

  it should "set sentBytes metrics in the underlying registry" in new Fixture {
    registry.sentBytes.update(3)
    underlyingHistogram("akka.http.responses.bytes") shouldBe 3L

    registry.sentBytes.update(3, dimensions)
    underlyingHistogram("akka.http.responses.bytes", dimensions) shouldBe 3L
  }

  it should "set connected metrics in the underlying registry" in new Fixture {
    registry.connected.inc()
    underlyingCounter("akka.http.connections.active") shouldBe 1L
  }

  it should "set connections metrics in the underlying registry" in new Fixture {
    registry.connections.inc()
    underlyingCounter("akka.http.connections") shouldBe 1L
  }
} 
Example 105
Source File: PrometheusSettings.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.prometheus

import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import fr.davit.akka.http.metrics.core.HttpMetricsSettings
import fr.davit.akka.http.metrics.prometheus.Quantiles.Quantile

import scala.concurrent.duration._

sealed trait HistogramConfig

sealed trait TimerConfig

final case class Quantiles(qs: List[Quantile], maxAge: FiniteDuration = 10.minutes, ageBuckets: Int = 5)
    extends HistogramConfig
    with TimerConfig

object Quantiles {

  final case class Quantile(percentile: Double, error: Double = 0.001)

  def apply(percentiles: Double*): Quantiles = {
    val quantiles = percentiles.map { p =>
      // the higher the percentile, the lowe the error
      val error = (1 - p) / 10
      Quantile(p, error)
    }
    Quantiles(quantiles.toList)
  }
}

final case class Buckets(bs: List[Double]) extends HistogramConfig with TimerConfig

object Buckets {
  def apply(b: Double*): Buckets = Buckets(b.toList)
}

final case class PrometheusSettings(
    namespace: String,
    defineError: HttpResponse => Boolean,
    includeMethodDimension: Boolean,
    includePathDimension: Boolean,
    includeStatusDimension: Boolean,
    receivedBytesConfig: HistogramConfig,
    durationConfig: TimerConfig,
    sentBytesConfig: HistogramConfig
) extends HttpMetricsSettings {

  override def withNamespace(namespace: String): PrometheusSettings =
    copy(namespace = namespace)

  override def withDefineError(fn: HttpResponse => Boolean): PrometheusSettings =
    copy(defineError = defineError)

  override def withIncludeMethodDimension(include: Boolean): PrometheusSettings =
    copy(includeMethodDimension = include)

  override def withIncludePathDimension(include: Boolean): PrometheusSettings =
    copy(includePathDimension = include)

  override def withIncludeStatusDimension(include: Boolean): PrometheusSettings =
    copy(includeStatusDimension = include)

  def withReceivedBytesConfig(config: HistogramConfig): PrometheusSettings =
    copy(receivedBytesConfig = config)

  def withDurationConfig(config: TimerConfig): PrometheusSettings =
    copy(durationConfig = config)

  def withSentBytesConfig(config: HistogramConfig): PrometheusSettings =
    copy(sentBytesConfig = config)
}

object PrometheusSettings {

  // generic durations adapted to network durations in seconds
  val DurationBuckets: Buckets = {
    Buckets(0.005, 0.01, .025, .05, .075, .1, .25, .5, .75, 1, 2.5, 5, 7.5, 10)
  }

  // generic buckets adapted to network messages sized
  val BytesBuckets: Buckets = {
    val buckets = Range(0, 1000, 100) ++ Range(1000, 10000, 1000) ++ Range(10000, 100000, 10000)
    Buckets(buckets.map(_.toDouble).toList)
  }

  // basic quantiles
  val DefaultQuantiles: Quantiles = Quantiles(0.75, 0.95, 0.98, 0.99, 0.999)

  val default: PrometheusSettings = PrometheusSettings(
    namespace = "akka_http",
    defineError = _.status.isInstanceOf[StatusCodes.ServerError],
    includeMethodDimension = false,
    includePathDimension = false,
    includeStatusDimension = false,
    receivedBytesConfig = BytesBuckets,
    durationConfig = DurationBuckets,
    sentBytesConfig = BytesBuckets
  )

} 
Example 106
Source File: PrometheusMarshallersSpec.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.prometheus.marshalling

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import fr.davit.akka.http.metrics.core.HttpMetricsRegistry.StatusGroupDimension
import fr.davit.akka.http.metrics.core.scaladsl.server.HttpMetricsDirectives.metrics
import fr.davit.akka.http.metrics.prometheus.{PrometheusRegistry, PrometheusSettings}
import io.prometheus.client.CollectorRegistry
import org.scalatest.BeforeAndAfterAll
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

import scala.concurrent.duration._

class PrometheusMarshallersSpec extends AnyFlatSpec with Matchers with ScalatestRouteTest with BeforeAndAfterAll {

  trait Fixture extends PrometheusMarshallers {

    val registry = PrometheusRegistry(
      new CollectorRegistry(),
      PrometheusSettings.default.withIncludeStatusDimension(true)
    )

    io.prometheus.client.Counter
      .build("other_metric", "An other metric")
      .register(registry.underlying)
  }

  override def afterAll(): Unit = {
    cleanUp()
    super.afterAll()
  }

  "PrometheusMarshallers" should "expose metrics as prometheus format" in new Fixture {
    // register labeled metrics so they appear at least once
    // use metrics so they appear in the report
    val dimensions = Seq(StatusGroupDimension(StatusCodes.OK))
    registry.requests.inc()
    registry.receivedBytes.update(10)
    registry.active.inc()
    registry.responses.inc(dimensions)
    registry.errors.inc(dimensions)
    registry.duration.observe(1.second, dimensions)
    registry.sentBytes.update(10, dimensions)

    Get() ~> metrics(registry) ~> check {
      response.entity.contentType shouldBe PrometheusMarshallers.PrometheusContentType
      val text = responseAs[String]
      // println(text)
      val metrics = text
        .split('\n')
        .filterNot(_.startsWith("#"))
        .map(_.takeWhile(c => c != ' ' && c != '{'))
        .distinct
      metrics should contain theSameElementsAs Seq(
        "akka_http_requests_active",
        "akka_http_requests_total",
        "akka_http_requests_size_bytes_bucket",
        "akka_http_requests_size_bytes_count",
        "akka_http_requests_size_bytes_sum",
        "akka_http_responses_total",
        "akka_http_responses_errors_total",
        "akka_http_responses_duration_seconds_bucket",
        "akka_http_responses_duration_seconds_count",
        "akka_http_responses_duration_seconds_sum",
        "akka_http_responses_size_bytes_bucket",
        "akka_http_responses_size_bytes_count",
        "akka_http_responses_size_bytes_sum",
        "akka_http_connections_active",
        "akka_http_connections_total",
        "other_metric"
      )
    }
  }
} 
Example 107
Source File: HttpMetricsSettings.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.core

import akka.http.scaladsl.model.{HttpResponse, StatusCodes}

trait HttpMetricsSettings {

  
  def includeStatusDimension: Boolean

  def withNamespace(namespace: String): HttpMetricsSettings
  def withDefineError(fn: HttpResponse => Boolean): HttpMetricsSettings
  def withIncludeMethodDimension(include: Boolean): HttpMetricsSettings
  def withIncludePathDimension(include: Boolean): HttpMetricsSettings
  def withIncludeStatusDimension(include: Boolean): HttpMetricsSettings
}

object HttpMetricsSettings {

  val default: HttpMetricsSettings = apply(
    "akka.http",
    _.status.isInstanceOf[StatusCodes.ServerError],
    includeMethodDimension = false,
    includePathDimension = false,
    includeStatusDimension = false
  )

  def apply(
      namespace: String,
      defineError: HttpResponse => Boolean,
      includeMethodDimension: Boolean,
      includePathDimension: Boolean,
      includeStatusDimension: Boolean
  ): HttpMetricsSettings = HttpMetricsSettingsImpl(
    namespace,
    defineError,
    includeMethodDimension,
    includePathDimension,
    includeStatusDimension
  )

  private case class HttpMetricsSettingsImpl(
      namespace: String,
      defineError: HttpResponse => Boolean,
      includeMethodDimension: Boolean,
      includePathDimension: Boolean,
      includeStatusDimension: Boolean
  ) extends HttpMetricsSettings {

    override def withNamespace(namespace: String): HttpMetricsSettings =
      copy(namespace = namespace)
    override def withDefineError(fn: HttpResponse => Boolean): HttpMetricsSettings =
      copy(defineError = fn)
    override def withIncludeMethodDimension(include: Boolean): HttpMetricsSettings =
      copy(includeMethodDimension = include)
    override def withIncludePathDimension(include: Boolean): HttpMetricsSettings =
      copy(includePathDimension = include)
    override def withIncludeStatusDimension(include: Boolean): HttpMetricsSettings =
      copy(includeStatusDimension = include)

  }
} 
Example 108
Source File: HttpMetricsDirectivesSpec.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.core.scaladsl.server

import akka.http.scaladsl.marshalling.PredefinedToEntityMarshallers._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import fr.davit.akka.http.metrics.core.TestRegistry
import fr.davit.akka.http.metrics.core.scaladsl.model.PathLabelHeader
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers

class HttpMetricsDirectivesSpec extends AnyFlatSpec with Matchers with ScalatestRouteTest {

  import HttpMetricsDirectives._

  "HttpMetricsDirectives" should "expose the registry" in {
    implicit val marshaller = StringMarshaller.compose[TestRegistry](r => s"active: ${r.active.value()}")
    val registry            = new TestRegistry()
    registry.active.inc()

    val route = path("metrics") {
      metrics(registry)
    }

    Get("/metrics") ~> route ~> check {
      responseAs[String] shouldBe "active: 1"
    }
  }

  it should "put label on path" in {
    val route = pathPrefixLabeled("api") {
      pathPrefix("user" / LongNumber) { _ =>
        path("address") {
          complete(StatusCodes.OK)
        }
      }
    }

    Get("/api/user/1234/address") ~> route ~> check {
      header[PathLabelHeader] shouldBe Some(PathLabelHeader("/api"))
    }
  }

  it should "combine labelled segments" in {
    val route = pathPrefixLabeled("api") {
      pathPrefixLabeled("user" / LongNumber, "user/:userId") { _ =>
        pathLabeled("address") {
          complete(StatusCodes.OK)
        }
      }
    }

    Get("/api/user/1234/address") ~> route ~> check {
      header[PathLabelHeader] shouldBe Some(PathLabelHeader("/api/user/:userId/address"))
    }
  }

  it should "not add extra header when label directives are not used" in {
    val route = pathPrefix("api") {
      pathPrefix("user" / LongNumber) { _ =>
        path("address") {
          complete(StatusCodes.OK)
        }
      }
    }

    Get("/api/user/1234/address") ~> route ~> check {
      header[PathLabelHeader] shouldBe empty
    }
  }
} 
Example 109
Source File: DatadogRegistrySpec.scala    From akka-http-metrics   with Apache License 2.0 5 votes vote down vote up
package fr.davit.akka.http.metrics.datadog

import java.net.InetSocketAddress

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.io.{IO, Udp}
import akka.testkit.{TestKit, TestProbe}
import com.timgroup.statsd.NonBlockingStatsDClient
import fr.davit.akka.http.metrics.core.HttpMetricsRegistry.{PathDimension, StatusGroupDimension}
import org.scalatest.BeforeAndAfterAll
import org.scalatest.flatspec.AnyFlatSpecLike
import org.scalatest.matchers.should.Matchers

import scala.concurrent.duration._

class DatadogRegistrySpec extends TestKit(ActorSystem("DatadogRegistrySpec")) with AnyFlatSpecLike with Matchers with BeforeAndAfterAll {

  val dimensions = Seq(StatusGroupDimension(StatusCodes.OK), PathDimension("/api"))

  def withFixture(test: (TestProbe, DatadogRegistry) => Any) = {
    val statsd = TestProbe()
    statsd.send(IO(Udp), Udp.Bind(statsd.ref, new InetSocketAddress(0)))
    val port = statsd.expectMsgType[Udp.Bound].localAddress.getPort
    val socket = statsd.sender()
    val client = new NonBlockingStatsDClient("", "localhost", port)
    val registry = DatadogRegistry(client)
    try {
      test(statsd, registry)
    } finally {
      client.close()
      socket ! Udp.Unbind
    }
  }

  override def afterAll(): Unit = {
    shutdown()
    super.afterAll()
  }

  "DatadogRegistry" should "send active datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.active.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.requests_active:1|c"
  }

  it should "send requests datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.requests.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.requests_count:1|c"
  }

  it should "send receivedBytes datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.receivedBytes.update(3)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.requests_bytes:3|d"

    registry.receivedBytes.update(3, dimensions)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.requests_bytes:3|d|#path:/api,status:2xx"
  }

  it should "send responses datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.responses.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_count:1|c"

    registry.responses.inc(dimensions)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_count:1|c|#path:/api,status:2xx"
  }

  it should "send errors datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.errors.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_errors_count:1|c"

    registry.errors.inc(dimensions)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_errors_count:1|c|#path:/api,status:2xx"
  }

  it should "send duration datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.duration.observe(3.seconds)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_duration:3000|d"

    registry.duration.observe(3.seconds, dimensions)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_duration:3000|d|#path:/api,status:2xx"
  }

  it should "send sentBytes datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.sentBytes.update(3)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_bytes:3|d"

    registry.sentBytes.update(3, dimensions)
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.responses_bytes:3|d|#path:/api,status:2xx"
  }

  it should "send connected datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.connected.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.connections_active:1|c"
  }
  it should "send connections datagrams to the statsd server" in withFixture { (statsd, registry) =>
    registry.connections.inc()
    statsd.expectMsgType[Udp.Received].data.utf8String shouldBe "akka.http.connections_count:1|c"
  }
} 
Example 110
Source File: ConsumerCommands.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._
import akka.pattern.ask
import akka.util.Timeout
import com.omearac.consumers.DataConsumer.{ConsumerActorReply, ManuallyInitializeStream, ManuallyTerminateStream}

import scala.concurrent.duration._



trait ConsumerCommands {
  def dataConsumer: ActorRef

  def eventConsumer: ActorRef

  def log: LoggingAdapter

  val dataConsumerHttpCommands: Route = pathPrefix("data_consumer") {
    implicit val timeout = Timeout(10 seconds)
    path("stop") {
      get {
        onSuccess(dataConsumer ? ManuallyTerminateStream) {
          case m: ConsumerActorReply => log.info(m.message); complete(StatusCodes.OK, m.message);
          case _ => complete(StatusCodes.InternalServerError)
        }
      }
    } ~
      path("start") {
        get {
          onSuccess(dataConsumer ? ManuallyInitializeStream) {
            case m: ConsumerActorReply => log.info(m.message); complete(StatusCodes.OK, m.message)
            case _ => complete(StatusCodes.InternalServerError)
          }
        }
      }
  }

  val eventConsumerHttpCommands: Route = pathPrefix("event_consumer") {
    implicit val timeout = Timeout(10 seconds)
    path("stop") {
      get {
        onSuccess(eventConsumer ? ManuallyTerminateStream) {
          case m: ConsumerActorReply => log.info(m.message); complete(StatusCodes.OK, m.message);
          case _ => complete(StatusCodes.InternalServerError)
        }
      }
    } ~
      path("start") {
        get {
          onSuccess(eventConsumer ? ManuallyInitializeStream) {
            case m: ConsumerActorReply => log.info(m.message); complete(StatusCodes.OK, m.message)
            case _ => complete(StatusCodes.InternalServerError)
          }
        }
      }
  }

} 
Example 111
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 112
Source File: YARNComponentActor.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.yarn

import akka.actor.{Actor, ActorSystem}
import akka.http.scaladsl.model.{HttpMethods, StatusCodes}
import akka.stream.ActorMaterializer
import org.apache.openwhisk.common.Logging
import org.apache.openwhisk.core.entity.ExecManifest.ImageName
import org.apache.openwhisk.core.yarn.YARNComponentActor.{CreateContainerAsync, RemoveContainer}
import spray.json.{JsArray, JsNumber, JsObject, JsString}

import scala.concurrent.ExecutionContext


object YARNComponentActor {
  case object CreateContainerAsync
  case class RemoveContainer(component_instance_name: String)
}

class YARNComponentActor(actorSystem: ActorSystem,
                         logging: Logging,
                         yarnConfig: YARNConfig,
                         serviceName: String,
                         imageName: ImageName)
    extends Actor {

  implicit val as: ActorSystem = actorSystem
  implicit val materializer: ActorMaterializer = ActorMaterializer()
  implicit val ec: ExecutionContext = actorSystem.dispatcher

  //Adding a container via the YARN REST API is actually done by flexing the component's container pool to a certain size.
  // This actor must track the current containerCount in order to make the correct scale-up request.
  var containerCount: Int = 0

  def receive: PartialFunction[Any, Unit] = {
    case CreateContainerAsync =>
      sender ! createContainerAsync

    case RemoveContainer(component_instance_name) =>
      sender ! removeContainer(component_instance_name)

    case input =>
      throw new IllegalArgumentException("Unknown input: " + input)
      sender ! false
  }

  def createContainerAsync(): Unit = {
    logging.info(this, s"Using YARN to create a container with image ${imageName.name}...")

    val body = JsObject("number_of_containers" -> JsNumber(containerCount + 1)).compactPrint
    val response = YARNRESTUtil.submitRequestWithAuth(
      yarnConfig.authType,
      HttpMethods.PUT,
      s"${yarnConfig.masterUrl}/app/v1/services/$serviceName/components/${imageName.name}",
      body)
    response match {
      case httpresponse(StatusCodes.OK, content) =>
        logging.info(this, s"Added container: ${imageName.name}. Response: $content")
        containerCount += 1

      case httpresponse(_, _) => YARNRESTUtil.handleYARNRESTError(logging)
    }
  }

  def removeContainer(component_instance_name: String): Unit = {
    logging.info(this, s"Removing ${imageName.name} container: $component_instance_name ")
    if (containerCount <= 0) {
      logging.warn(this, "Already at 0 containers")
    } else {
      val body = JsObject(
        "components" -> JsArray(
          JsObject(
            "name" -> JsString(imageName.name),
            "decommissioned_instances" -> JsArray(JsString(component_instance_name))))).compactPrint
      val response = YARNRESTUtil.submitRequestWithAuth(
        yarnConfig.authType,
        HttpMethods.PUT,
        s"${yarnConfig.masterUrl}/app/v1/services/$serviceName",
        body)
      response match {
        case httpresponse(StatusCodes.OK, content) =>
          logging.info(
            this,
            s"Successfully removed ${imageName.name} container: $component_instance_name. Response: $content")
          containerCount -= 1

        case httpresponse(_, _) => YARNRESTUtil.handleYARNRESTError(logging)
      }
    }
  }
} 
Example 113
Source File: OpenWhiskEventsTests.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.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import com.typesafe.config.ConfigFactory
import io.prometheus.client.CollectorRegistry
import kamon.Kamon
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

import scala.concurrent.duration._
import scala.util.Try

@RunWith(classOf[JUnitRunner])
class OpenWhiskEventsTests extends KafkaSpecBase {
  behavior of "Server"

  it should "start working http server" in {
    val httpPort = freePort()
    val globalConfig = system.settings.config
    val config = ConfigFactory.parseString(s"""
           | akka.kafka.consumer.kafka-clients {
           |  bootstrap.servers = "localhost:$kafkaPort"
           | }
           | kamon {
           |  metric {
           |    tick-interval = 50 ms
           |    optimistic-tick-alignment = no
           |  }
           | }
           | whisk {
           |  user-events {
           |    port = $httpPort
           |    rename-tags {
           |      namespace = "ow_namespace"
           |    }
           |  }
           | }
         """.stripMargin).withFallback(globalConfig)
    CollectorRegistry.defaultRegistry.clear()
    val binding = OpenWhiskEvents.start(config).futureValue
    val res = get("localhost", httpPort, "/ping")
    res shouldBe Some(StatusCodes.OK, "pong")

    //Check if metrics using Kamon API gets included in consolidated Prometheus
    Kamon.counter("fooTest").withoutTags().increment(42)
    sleep(1.second)
    val metricRes = get("localhost", httpPort, "/metrics")
    metricRes.get._2 should include("fooTest")

    binding.unbind().futureValue
  }

  def get(host: String, port: Int, path: String = "/") = {
    val response = Try {
      Http()
        .singleRequest(HttpRequest(uri = s"http://$host:$port$path"))
        .futureValue
    }.toOption

    response.map { res =>
      (res.status, Unmarshal(res).to[String].futureValue)
    }
  }
} 
Example 114
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 115
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 116
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 117
Source File: BasicAuthenticationTestSuite.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package endpoints4s.algebra.server

import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.http.scaladsl.model.headers.{BasicHttpCredentials, `WWW-Authenticate`}
import endpoints4s.algebra.BasicAuthenticationTestApi

trait BasicAuthenticationTestSuite[T <: BasicAuthenticationTestApi] extends EndpointsTestSuite[T] {

  "BasicAuthentication" should {

    "reject unauthenticated requests" in {
      serveEndpoint(serverApi.protectedEndpoint, Some("Hello!")) { port =>
        val request = HttpRequest(uri = s"http://localhost:$port/users")
        whenReady(sendAndDecodeEntityAsText(request)) {
          case (response, entity) =>
            response.status shouldBe StatusCodes.Unauthorized
            response
              .header[`WWW-Authenticate`]
              .exists(_.challenges.exists(_.scheme == "Basic")) shouldBe true
            entity shouldBe ""
            ()
        }
      }
    }

    "accept authenticated requests" in {
      serveEndpoint(serverApi.protectedEndpoint, Some("Hello!")) { port =>
        val request =
          HttpRequest(uri = s"http://localhost:$port/users")
            .addCredentials(BasicHttpCredentials("admin", "foo"))
        whenReady(sendAndDecodeEntityAsText(request)) {
          case (response, entity) =>
            response.status shouldBe StatusCodes.OK
            entity shouldBe "Hello!"
            ()
        }
      }
    }

    "reject unauthenticated requests with invalid parameters before handling authorization" in {
      serveEndpoint(serverApi.protectedEndpointWithParameter, Some("Hello!")) { port =>
        val request = HttpRequest(uri = s"http://localhost:$port/users/foo")
        whenReady(sendAndDecodeEntityAsText(request)) {
          case (response, entity) =>
            response.status shouldBe StatusCodes.BadRequest
            entity shouldBe "[\"Invalid integer value 'foo' for segment 'id'\"]"
            ()
        }
      }
    }

  }

} 
Example 118
Source File: CounterTest.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package quickstart

import java.net.ServerSocket

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpMethods, HttpRequest, StatusCodes}
import akka.http.scaladsl.server.Directives._
import org.scalatest.BeforeAndAfterAll

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
import org.scalatest.freespec.AsyncFreeSpec

class CounterTest extends AsyncFreeSpec with BeforeAndAfterAll {

  implicit val actorSystem: ActorSystem = ActorSystem()
  val routes = CounterServer.routes ~ DocumentationServer.routes
  val interface = "0.0.0.0"
  val port = findOpenPort()
  val server = Http().bindAndHandle(routes, interface, port)

  override protected def afterAll(): Unit = {
    Await.result(
      Await.result(server, 10.seconds).terminate(3.seconds),
      15.seconds
    )
    Await.result(actorSystem.terminate(), 5.seconds)
    super.afterAll()
  }

  "CounterServer" - {
    "Query counter value" in {
      for {
        response <- Http().singleRequest(
          HttpRequest(uri = uri("/current-value"))
        )
        entity <- response.entity.toStrict(1.second)
      } yield {
        assert(response.status == StatusCodes.OK)
        assert(entity.contentType == ContentTypes.`application/json`)
        assert(entity.data.utf8String == "{\"value\":0}")
      }
    }
    "Increment counter value" in {
      val request =
        HttpRequest(
          method = HttpMethods.POST,
          uri = uri("/increment"),
          entity = HttpEntity(ContentTypes.`application/json`, "{\"step\":1}")
        )
      for {
        response <- Http().singleRequest(request)
      } yield {
        assert(response.status == StatusCodes.OK)
      }
    }
    "Query API documentation" in {
      for {
        response <- Http().singleRequest(
          HttpRequest(uri = uri("/documentation.json"))
        )
        entity <- response.entity.toStrict(1.second)
      } yield {
        assert(response.status == StatusCodes.OK)
        assert(entity.contentType == ContentTypes.`application/json`)
      }
    }
  }

  def findOpenPort(): Int = {
    val socket = new ServerSocket(0)
    try socket.getLocalPort
    finally if (socket != null) socket.close()
  }

  def uri(suffix: String) = s"http://$interface:$port$suffix"

} 
Example 119
Source File: StubAkkaHttpMockWebServer.scala    From wix-http-testkit   with MIT License 5 votes vote down vote up
package com.wix.e2e.http.server.internals

import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import com.wix.e2e.http._
import com.wix.e2e.http.api.{AdjustableServerBehavior, MockWebServer, StubWebServer}

import scala.collection.mutable.ListBuffer

class StubAkkaHttpMockWebServer(initialHandlers: Seq[RequestHandler], specificPort: Option[Int])
  extends AkkaHttpMockWebServer(specificPort, initialHandlers)
  with StubWebServer {


  def recordedRequests: Seq[HttpRequest] = this.synchronized {
    requests.toSeq
  }

  def clearRecordedRequests() = this.synchronized {
    requests.clear()
  }

  private val requests = ListBuffer.empty[HttpRequest]

  private val SuccessfulHandler: RequestHandler = { case _ => HttpResponse(status = StatusCodes.OK) }
  private def StubServerHandlers = (currentHandlers :+ SuccessfulHandler).reduce(_ orElse _)
  private val RequestRecorderHandler: RequestHandler = { case r =>
    this.synchronized {
      requests.append(r)
    }
    StubServerHandlers.apply(r)
  }

  protected val serverBehavior = RequestRecorderHandler
}

class MockAkkaHttpWebServer(initialHandlers: Seq[RequestHandler], specificPort: Option[Int])
  extends AkkaHttpMockWebServer(specificPort, initialHandlers)
  with MockWebServer {

  private val NotFoundHandler: RequestHandler = { case _ => HttpResponse(status = StatusCodes.NotFound) }
  private def MockServerHandlers = (currentHandlers :+ NotFoundHandler).reduce(_ orElse _)
  private val AdjustableHandler: RequestHandler = { case r =>
    MockServerHandlers.apply(r)
  }

  protected val serverBehavior = AdjustableHandler
}

trait AdjustableServerBehaviorSupport extends AdjustableServerBehavior {
  private val localHandlers: ListBuffer[RequestHandler] = ListBuffer(initialHandlers:_*)

  def initialHandlers: Seq[RequestHandler]

  def currentHandlers: Seq[RequestHandler] = this.synchronized {
    localHandlers.toSeq
  }

  def appendAll(handlers: RequestHandler*) = this.synchronized {
    localHandlers.appendAll(handlers)
  }

  def replaceWith(handlers: RequestHandler*) = this.synchronized {
    localHandlers.clear()
    appendAll(handlers:_*)
  }
} 
Example 120
Source File: K8sProbesTest.scala    From healthchecks   with MIT License 5 votes vote down vote up
package com.chatwork.healthcheck.k8s

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, StatusCodes}
import akka.stream.ActorMaterializer
import com.github.everpeace.healthchecks._
import com.github.everpeace.healthchecks.k8s._
import org.scalatest._

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

class K8sProbesTest extends FreeSpec with Matchers {

  private def fixture(probe: K8sProbe, probes: K8sProbe*) = new {}

  "K8sProbes" - {
    "should start successfully and return correct response" in {
      implicit val system = ActorSystem()
      implicit val am     = ActorMaterializer()
      implicit val ec     = system.dispatcher

      val probeBinding = bindAndHandleProbes(
        readinessProbe(healthCheck("readiness_check")(healthy)),
        livenessProbe(asyncHealthCheck("liveness_check")(Future(healthy)))
      )

      def requestToLivenessProbe =
        Http().singleRequest(HttpRequest(uri = "http://localhost:8086/live"))
      def requestToReadinessProbe =
        Http().singleRequest(HttpRequest(uri = "http://localhost:8086/ready"))

      val livenessResponse = Await.result(requestToLivenessProbe, 10 seconds)
      val redinessResponse = Await.result(requestToReadinessProbe, 10 seconds)

      livenessResponse.status shouldEqual StatusCodes.OK
      redinessResponse.status shouldEqual StatusCodes.OK

      system.terminate()
    }
  }
} 
Example 121
Source File: TopicSpec.scala    From sns   with Apache License 2.0 5 votes vote down vote up
package me.snov.sns.api

import java.util.concurrent.TimeUnit

import akka.actor.ActorRef
import akka.http.scaladsl.model.{FormData, HttpResponse, StatusCodes}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.testkit.{TestActor, TestProbe}
import akka.util.Timeout
import me.snov.sns.actor.SubscribeActor.{CmdDeleteTopic, CmdCreateTopic}
import me.snov.sns.model.Topic
import org.scalatest.{Matchers, WordSpec}

class TopicSpec extends WordSpec with Matchers with ScalatestRouteTest {
  implicit val timeout = new Timeout(100, TimeUnit.MILLISECONDS)

  val probe = TestProbe()
  val route = TopicApi.route(probe.ref)

  "Requires topic name" in {
    Post("/", FormData(Map("Action" -> "CreateTopic"))) ~> route ~> check {
      status shouldBe StatusCodes.BadRequest
    }
  }

  "Validates topic name" in {
    Post("/", FormData(Map("Action" -> "CreateTopic", "Name" -> "f$$"))) ~> route ~> check {
      status shouldBe StatusCodes.BadRequest
    }
  }

  "TopicDelete validates topic name" in {
    Post("/", FormData(Map("Action" -> "DeleteTopic", "TopicArn" -> "f$$"))) ~> route ~> check {
      status shouldBe StatusCodes.BadRequest
    }
  }

  "Sends create command to actor" in {
    probe.setAutoPilot(new TestActor.AutoPilot {
      def run(sender: ActorRef, msg: Any) = {
        sender ! new Topic("foo", "bar")
        this
      }
    })
    Post("/", FormData(Map("Action" -> "CreateTopic", "Name" -> "foo"))) ~> route ~> check {
      probe.expectMsg(CmdCreateTopic("foo"))
    }
  }

  "Sends delete command to actor" in {
    probe.setAutoPilot(new TestActor.AutoPilot {
      def run(sender: ActorRef, msg: Any) = {
        sender ! new Topic("foo", "bar")
        this
      }
    })
    Post("/", FormData(Map("Action" -> "DeleteTopic", "TopicArn" -> "arn-foo"))) ~> route ~> check {
      probe.expectMsg(CmdDeleteTopic("arn-foo"))
    }
  }
} 
Example 122
Source File: PublishSpec.scala    From sns   with Apache License 2.0 5 votes vote down vote up
package me.snov.sns.api

import java.util.concurrent.TimeUnit

import akka.actor.ActorRef
import akka.http.scaladsl.model.{FormData, StatusCodes}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.testkit.{TestActor, TestProbe}
import akka.util.Timeout
import me.snov.sns.actor.PublishActor.CmdPublish
import me.snov.sns.model.{Message, MessageAttribute}
import org.scalatest.{Matchers, WordSpec}

class PublishSpec extends WordSpec with Matchers with ScalatestRouteTest {
  implicit val timeout = new Timeout(100, TimeUnit.MILLISECONDS)

  val probe = TestProbe()
  val route = PublishApi.route(probe.ref)

  "Publish requires topic ARN" in {
    val params = Map("Action" -> "Publish")
    Post("/", FormData(params)) ~> route ~> check {
      status shouldBe StatusCodes.BadRequest
    }
  }

  "Sends publish command" in {
    val params = Map(
      "Action" -> "Publish",
      "TopicArn" -> "foo",
      "Message" -> "bar"
    )

    probe.setAutoPilot(new TestActor.AutoPilot {
      def run(sender: ActorRef, msg: Any) = {
        sender ! Message(Map("default" -> "foo"))
        this
      }
    })
    Post("/", FormData(params)) ~> route ~> check {
      probe.expectMsg(CmdPublish("foo", Map("default" -> "bar"), Map.empty))
    }
  }

  "Sends publish command to TargetArn" in {
    val params = Map(
      "Action" -> "Publish",
      "TargetArn" -> "foo",
      "Message" -> "bar"
    )

    probe.setAutoPilot(new TestActor.AutoPilot {
      def run(sender: ActorRef, msg: Any) = {
        sender ! Message(Map("default" -> "foo"))
        this
      }
    })
    Post("/", FormData(params)) ~> route ~> check {
      probe.expectMsg(CmdPublish("foo", Map("default" -> "bar"), Map.empty))
    }
  }

  "Sends publish command with attributes" in {
    val params = Map(
      "Action" -> "Publish",
      "TopicArn" -> "foo",
      "Message" -> "bar",
      "MessageAttributes.entry.1.Value.DataType" -> "String",
      "MessageAttributes.entry.1.Value.StringValue" -> "AttributeValue",
      "MessageAttributes.entry.1.Name" -> "AttributeName"
    )

    probe.setAutoPilot(new TestActor.AutoPilot {
      def run(sender: ActorRef, msg: Any) = {
        sender ! Message(Map("default" -> "foo"), messageAttributes = Map("AttributeName" -> MessageAttribute("StringValue", "AttributeValue")))
        this
      }
    })
    Post("/", FormData(params)) ~> route ~> check {
      probe.expectMsg(CmdPublish("foo", Map("default" -> "bar"),Map("AttributeName" -> MessageAttribute("StringValue", "AttributeValue"))))
    }
  }
} 
Example 123
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 124
Source File: DonutRoute.scala    From scala-for-beginners   with Apache License 2.0 5 votes vote down vote up
package com.allaboutscala.donutstore.httpserver.routes

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

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 125
Source File: OrderServiceApi.scala    From 006877   with MIT License 5 votes vote down vote up
package aia.integration

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

import akka.actor._
import akka.pattern.ask
import akka.util.Timeout

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.MediaTypes._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._

import scala.xml.{ Elem, XML, NodeSeq }
import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._ 

class OrderServiceApi(
  system: ActorSystem, 
  timeout: Timeout, 
  val processOrders: ActorRef
) extends OrderService {
  implicit val requestTimeout = timeout
  implicit def executionContext = system.dispatcher
}

trait OrderService {
  val processOrders: ActorRef

  implicit def executionContext: ExecutionContext

  implicit def requestTimeout: Timeout


  val routes = getOrder ~ postOrders



  def getOrder = get {
    pathPrefix("orders" / IntNumber) { id =>
      onSuccess(processOrders.ask(OrderId(id))) {
        case result: TrackingOrder =>
          complete(<statusResponse>
            <id>{ result.id }</id>
            <status>{ result.status }</status>
          </statusResponse>)
        
        case result: NoSuchOrder => 
          complete(StatusCodes.NotFound)
      }
    }
  }

  

  def postOrders = post {
    path("orders") {
      entity(as[NodeSeq]) { xml =>
        val order = toOrder(xml)
        onSuccess(processOrders.ask(order)) {
          case result: TrackingOrder =>
            complete(
              <confirm>
                <id>{ result.id }</id>
                <status>{ result.status }</status>
              </confirm>
            )
        
          case result =>
            complete(StatusCodes.BadRequest)
        }
      }
    }
  }  



  def toOrder(xml: NodeSeq): Order = {
    val order = xml \\ "order"
    val customer = (order \\ "customerId").text
    val productId = (order \\ "productId").text
    val number = (order \\ "number").text.toInt
    new Order(customer, productId, number)
  }

} 
Example 126
Source File: OrderServiceTest.scala    From 006877   with MIT License 5 votes vote down vote up
package aia.integration

import scala.concurrent.duration._
import scala.xml.NodeSeq
import akka.actor.Props

import akka.http.scaladsl.marshallers.xml.ScalaXmlSupport._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server._
import akka.http.scaladsl.testkit.ScalatestRouteTest

import org.scalatest.{ Matchers, WordSpec }
 
class OrderServiceTest extends WordSpec 
    with Matchers 
    with OrderService
    with ScalatestRouteTest {

  implicit val executionContext = system.dispatcher
  implicit val requestTimeout = akka.util.Timeout(1 second)
  val processOrders = 
    system.actorOf(Props(new ProcessOrders), "orders")

  "The order service" should {
    "return NotFound if the order cannot be found" in {
      Get("/orders/1") ~> routes ~> check {
        status shouldEqual StatusCodes.NotFound
      }
    }

    "return the tracking order for an order that was posted" in {
      val xmlOrder = 
      <order><customerId>customer1</customerId>
        <productId>Akka in action</productId>
        <number>10</number>
      </order>
      
      Post("/orders", xmlOrder) ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        val xml = responseAs[NodeSeq]
        val id = (xml \\ "id").text.toInt
        val orderStatus = (xml \\ "status").text
        id shouldEqual 1
        orderStatus shouldEqual "received"
      }
      Get("/orders/1") ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        val xml = responseAs[NodeSeq]
        val id = (xml \\ "id").text.toInt
        val orderStatus = (xml \\ "status").text
        id shouldEqual 1
        orderStatus shouldEqual "processing"
      }
    }
  }
} 
Example 127
Source File: RoutingDSL.scala    From introduction-to-akkahttp   with Apache License 2.0 5 votes vote down vote up
package com.shashank.akkahttp.basic.routing

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.stream.{ActorMaterializer, Materializer}


object RoutingDSL {

  def main(args: Array[String]) {

    implicit val sys = ActorSystem("IntroductionToAkkaHttp")
    implicit val mat:Materializer = ActorMaterializer()

    val route =
      path("welcome"){
        get{
          complete {
            "welcome to rest service"
          }
        }
      } ~
      path("demo"){
        get{
          complete {
            "welcome to demonstration"
          }
        }
      }

    Http().bindAndHandle(route, "localhost", 8090)

  }

} 
Example 128
Source File: FileUploadStream.scala    From introduction-to-akkahttp   with Apache License 2.0 5 votes vote down vote up
package com.shashank.akkahttp.basic.routing

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, Multipart, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.stream.scaladsl.Framing
import akka.util.ByteString

import scala.concurrent.Future



object FileUploadStream extends BaseSpec{

  def main(args: Array[String]) {

    val route =
      extractRequestContext { ctx =>
        implicit val materializer = ctx.materializer
        implicit val ec = ctx.executionContext
 
        fileUpload("csv") {
          case (metadata, byteSource) =>
            val sumF: Future[Int] =
            // sum the numbers as they arrive so that we can
            byteSource.via(Framing.delimiter(ByteString("\n"), 1024))
              .mapConcat(_.utf8String.split(",").toVector)
              .map(_.toInt)
              .runFold(0) { (acc, n) => acc + n }
              onSuccess(sumF) { sum => complete(s"Sum: $sum") }
        }
      }

    //Test file upload stream
    val multipartForm =
      Multipart.FormData(Multipart.FormData.BodyPart.Strict(
        "csv",
        HttpEntity(ContentTypes.`text/plain(UTF-8)`, "2,3,5\n7,11,13,17,23\n29,31,37\n"),
        Map("filename" -> "primes.csv")))
 
    Post("/", multipartForm) ~> route ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual "Sum: 178"
    }

    system.terminate()
  }

}
//File upload direct
//curl --form "[email protected]" http://<host>:<port> 
Example 129
Source File: Failure.scala    From introduction-to-akkahttp   with Apache License 2.0 5 votes vote down vote up
package com.shashank.akkahttp.basic.routing

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.ExceptionHandler
import akka.stream.{ActorMaterializer, Materializer}


object Failure {

  def main(args: Array[String]) {

    implicit val sys = ActorSystem("IntroductionToAkkaHttp")
    implicit val mat:Materializer = ActorMaterializer()

    implicit def myExceptionHandler = ExceptionHandler {
      case _: ArithmeticException =>
        complete(HttpResponse(StatusCodes.BadRequest, entity = "Bad numbers, bad result!!!"))
      case e: Throwable => {
        println(e.getMessage)
        println(e.getStackTraceString)
        complete(HttpResponse(StatusCodes.BadRequest, entity = e.getMessage))
      }
    }

    val route =
      path("welcome"){
        get{
          complete {
            "welcome to rest service"
          }
        }
      } ~
      path("demo"){
        get {
          complete {
            100/0
            "welcome to demonstration"
          }
        }
      }

    Http().bindAndHandle(route, "localhost", 8090)
  }

} 
Example 130
Source File: Rejection.scala    From introduction-to-akkahttp   with Apache License 2.0 5 votes vote down vote up
package com.shashank.akkahttp.basic.routing

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpResponse, StatusCodes}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import akka.stream.{ActorMaterializer, Materializer}


object Rejection {

  def main(args: Array[String]) {

    implicit val sys = ActorSystem("IntroductionToAkkaHttp")
    implicit val mat:Materializer = ActorMaterializer()

    implicit def myRejectionHandler = RejectionHandler.newBuilder().handle{
      case MissingCookieRejection(cookieName) =>
        complete(HttpResponse(StatusCodes.BadRequest, entity = "No cookies, no service!!!"))
    }.handleNotFound {
      complete((StatusCodes.NotFound, "Not here!"))
    }.result()

    val route =
      path("welcome"){
        get{
          complete {
            "welcome to rest service"
          }
        }
      } ~
      path("demo"){
        get{
          complete {
            "welcome to demonstration"
          }
        }
      } ~
      path("wrong"){
        reject{
          ValidationRejection("Invalid path", None)
        }
      }

    Http().bindAndHandle(route, "localhost", 8090)

  }

} 
Example 131
Source File: CRUDHandlers.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter9

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.PathMatchers.Segment

trait GetRequestsHandler {
  def handleGet(cache: scala.collection.mutable.Map[String, TemperatureMeasurement]) =
    pathEndOrSingleSlash {
      complete {
        cache.map(keyValue => s"${keyValue._2.location},${keyValue._2.measurement}").mkString("\n")
      }
    } ~
      path(Segment) { id =>
        complete {
          cache.get(id) match {
            case Some(TemperatureMeasurement(location, measurement)) => s"Temperature for $location is $measurement"
            case None => StatusCodes.NotFound -> s"Not temperature measurement for $id"
          }
        }
      }
}

trait PostRequestsHandler {
  def handlePost(cache: scala.collection.mutable.Map[String, TemperatureMeasurement]) =
    entity(as[String]) { content =>
      complete {
        content.split(",") match {
          case Array(location, _) if cache.contains(location) =>
            StatusCodes.Conflict -> s"$location has a value already. To update it please use PUT method."
          case Array(location, measurement) =>
            cache.put(location, TemperatureMeasurement(location, measurement.toDouble))
            s"Measurement inserted for $location"
        }
      }
    }
}

trait PutRequestsHandler {
  def handlePut(cache: scala.collection.mutable.Map[String, TemperatureMeasurement]) =
    path(Segment) { id =>
      entity(as[String]) { updatedMeasurement =>
        complete {
          cache.get(id) match {
            case Some(TemperatureMeasurement(location, measurement)) =>
              cache.put(id, TemperatureMeasurement(location, updatedMeasurement.toDouble))
              s"New temperature for $location is $updatedMeasurement"
            case None =>
              StatusCodes.NotFound -> s"Not temperature measurement for $id"
          }
        }
      }
    }
}

trait DeleteRequestsHandler {
  def handleDelete(cache: scala.collection.mutable.Map[String, TemperatureMeasurement]) =
    path(Segment) { id =>
      complete {
        cache.get(id) match {
          case Some(TemperatureMeasurement(location, measurement)) =>
            cache.remove(id)
            s"Removed temperature for $location"
          case None =>
            StatusCodes.NotFound -> s"Not temperature measurement for $id"
        }
      }
    }
} 
Example 132
Source File: RouteExceptionHandler.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter9

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.ExceptionHandler
import akka.pattern.AskTimeoutException

trait RouteExceptionHandler {

  val routeExceptionHandler = ExceptionHandler {
    case _: ArithmeticException =>
      complete {
        StatusCodes.BadRequest -> "You values are incorrect. Probably b needs to be different from 0"
      }
    case _: AskTimeoutException =>
      complete {
        StatusCodes.ServiceUnavailable -> "Internal actor is not responding within 500 millis"
      }
  }
} 
Example 133
Source File: EncodingDecodingServerApplication.scala    From Akka-Cookbook   with MIT License 5 votes vote down vote up
package com.packt.chapter9

import akka.http.scaladsl.coding._
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.settings.ServerSettings
import com.typesafe.config.ConfigFactory

object EncodingDecodingServer extends HttpApp {
  val route =
    post {
      decodeRequestWith(Gzip, NoCoding) {
        entity(as[String]) { stringEntity =>
          encodeResponse {
            complete {
              println(s"Received $stringEntity")
              StatusCodes.OK -> s"Thank you for your encoded request [$stringEntity]."
            }
          }
        }
      }
    }
}

object EncodingDecodingServerApplication extends App {
  EncodingDecodingServer.startServer("0.0.0.0", 8088, ServerSettings(ConfigFactory.load))
} 
Example 134
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 135
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 136
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 137
Source File: HealthCheckRoutesSpec.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management

import akka.actor.ExtendedActorSystem
import akka.http.scaladsl.model.{ StatusCodes, Uri }
import akka.http.scaladsl.server._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.management.scaladsl.{ HealthChecks, ManagementRouteProviderSettings }
import org.scalatest.{ Matchers, WordSpec }

import scala.concurrent.Future

class HealthCheckRoutesSpec extends WordSpec with Matchers with ScalatestRouteTest {

  private val eas = system.asInstanceOf[ExtendedActorSystem]

  private def testRoute(
      readyResultValue: Future[Either[String, Unit]] = Future.successful(Right(())),
      aliveResultValue: Future[Either[String, Unit]] = Future.successful(Right(()))
  ): Route = {
    new HealthCheckRoutes(eas) {
      override protected val healthChecks: HealthChecks = new HealthChecks {
        override def readyResult(): Future[Either[String, Unit]] = readyResultValue
        override def ready(): Future[Boolean] = readyResultValue.map(_.isRight)
        override def aliveResult(): Future[Either[String, Unit]] = aliveResultValue
        override def alive(): Future[Boolean] = aliveResultValue.map(_.isRight)
      }
    }.routes(ManagementRouteProviderSettings(Uri("http://whocares"), readOnly = false))
  }

  tests("/ready", result => testRoute(readyResultValue = result))
  tests("/alive", result => testRoute(aliveResultValue = result))

  def tests(endpoint: String, route: Future[Either[String, Unit]] => Route) = {
    s"Health check ${endpoint} endpoint" should {
      "return 200 for Right" in {
        Get(endpoint) ~> route(Future.successful(Right(()))) ~> check {
          status shouldEqual StatusCodes.OK
        }
      }
      "return 500 for Left" in {
        Get(endpoint) ~> route(Future.successful(Left("com.someclass.MyCheck"))) ~> check {
          status shouldEqual StatusCodes.InternalServerError
          responseAs[String] shouldEqual "Not Healthy: com.someclass.MyCheck"
        }
      }
      "return 500 for fail" in {
        Get(endpoint) ~> route(Future.failed(new RuntimeException("darn it"))) ~> check {
          status shouldEqual StatusCodes.InternalServerError
          responseAs[String] shouldEqual "Health Check Failed: darn it"
        }
      }
    }
  }
} 
Example 138
Source File: LogLevelRoutesSpec.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management.loglevels.logback

import akka.actor.ExtendedActorSystem
import akka.http.javadsl.server.MalformedQueryParamRejection
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.Uri
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.management.scaladsl.ManagementRouteProviderSettings
import org.scalatest.Matchers
import org.scalatest.WordSpec
import org.slf4j.LoggerFactory
import akka.event.{ Logging => ClassicLogging }

class LogLevelRoutesSpec extends WordSpec with Matchers with ScalatestRouteTest {

  override def testConfigSource: String =
    """
      akka.loglevel = INFO
      """

  val routes = LogLevelRoutes
    .createExtension(system.asInstanceOf[ExtendedActorSystem])
    .routes(ManagementRouteProviderSettings(Uri("https://example.com"), readOnly = false))

  "The logback log level routes" must {

    "show log level of a Logger" in {
      Get("/loglevel/logback?logger=LogLevelRoutesSpec") ~> routes ~> check {
        responseAs[String]
      }
    }

    "change log level of a Logger" in {
      Put("/loglevel/logback?logger=LogLevelRoutesSpec&level=DEBUG") ~> routes ~> check {
        response.status should ===(StatusCodes.OK)
        LoggerFactory.getLogger("LogLevelRoutesSpec").isDebugEnabled should ===(true)
      }
    }

    "fail for unknown log level" in {
      Put("/loglevel/logback?logger=LogLevelRoutesSpec&level=MONKEY") ~> routes ~> check {
        rejection shouldBe an[MalformedQueryParamRejection]
      }
    }

    "not change loglevel if read only" in {
      val readOnlyRoutes = LogLevelRoutes
        .createExtension(system.asInstanceOf[ExtendedActorSystem])
        .routes(ManagementRouteProviderSettings(Uri("https://example.com"), readOnly = true))
      Put("/loglevel/logback?logger=LogLevelRoutesSpec&level=DEBUG") ~> readOnlyRoutes ~> check {
        response.status should ===(StatusCodes.Forbidden)
      }
    }

    "allow inspecting classic Akka loglevel" in {
      Get("/loglevel/akka") ~> routes ~> check {
        response.status should ===(StatusCodes.OK)
        responseAs[String] should ===("INFO")
      }
    }

    "allow changing classic Akka loglevel" in {
      Put("/loglevel/akka?level=DEBUG") ~> routes ~> check {
        response.status should ===(StatusCodes.OK)
        system.eventStream.logLevel should ===(ClassicLogging.DebugLevel)
      }
    }
  }

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

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{ HttpRequest, StatusCodes }
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.management.scaladsl.ManagementRouteProviderSettings
import akka.stream.ActorMaterializer
import akka.testkit.SocketUtil
import com.typesafe.config.ConfigFactory
import org.scalatest.{ Matchers, WordSpec }
import org.scalatest.concurrent.{ Eventually, ScalaFutures }
import org.scalatest.time.{ Millis, Seconds, Span }

class MultiDcSpec
    extends WordSpec
    with Matchers
    with ScalaFutures
    with ClusterHttpManagementJsonProtocol
    with Eventually {

  implicit val patience: PatienceConfig = PatienceConfig(timeout = Span(10, Seconds), interval = Span(50, Millis))

  val config = ConfigFactory.parseString(
    """
      |akka.actor.provider = "cluster"
      |akka.remote.log-remote-lifecycle-events = off
      |akka.remote.netty.tcp.hostname = "127.0.0.1"
      |#akka.loglevel = DEBUG
    """.stripMargin
  )

  "Http cluster management" must {
    "allow multiple DCs" in {
      val Vector(httpPortA, portA, portB) = SocketUtil.temporaryServerAddresses(3, "127.0.0.1").map(_.getPort)
      val dcA = ConfigFactory.parseString(
        s"""
           |akka.management.http.hostname = "127.0.0.1"
           |akka.management.http.port = $httpPortA
           |akka.cluster.seed-nodes = ["akka.tcp://[email protected]:$portA"]
           |akka.cluster.multi-data-center.self-data-center = "DC-A"
           |akka.remote.netty.tcp.port = $portA
          """.stripMargin
      )
      val dcB = ConfigFactory.parseString(
        s"""
           |akka.cluster.seed-nodes = ["akka.tcp://[email protected]:$portA"]
           |akka.cluster.multi-data-center.self-data-center = "DC-B"
           |akka.remote.netty.tcp.port = $portB
          """.stripMargin
      )

      implicit val dcASystem = ActorSystem("MultiDcSystem", config.withFallback(dcA))
      val dcBSystem = ActorSystem("MultiDcSystem", config.withFallback(dcB))
      implicit val materializer = ActorMaterializer()

      val routeSettings =
        ManagementRouteProviderSettings(selfBaseUri = s"http://127.0.0.1:$httpPortA", readOnly = false)

      try {
        Http()
          .bindAndHandle(ClusterHttpManagementRouteProvider(dcASystem).routes(routeSettings), "127.0.0.1", httpPortA)
          .futureValue

        eventually {
          val response =
            Http().singleRequest(HttpRequest(uri = s"http://127.0.0.1:$httpPortA/cluster/members")).futureValue
          response.status should equal(StatusCodes.OK)
          val members = Unmarshal(response.entity).to[ClusterMembers].futureValue
          members.members.size should equal(2)
          members.members.map(_.status) should equal(Set("Up"))
        }
      } finally {
        dcASystem.terminate()
        dcBSystem.terminate()
      }
    }
  }
} 
Example 140
Source File: ClusterHttpManagementRouteProviderSpec.scala    From akka-management   with Apache License 2.0 5 votes vote down vote up
package akka.management.cluster

import akka.actor.ExtendedActorSystem
import akka.cluster.Cluster
import akka.http.scaladsl.model.{ StatusCodes, Uri }
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.management.scaladsl.ManagementRouteProviderSettings
import org.scalatest.{ Matchers, WordSpec }

object ClusterHttpManagementRouteProviderSpec {}

class ClusterHttpManagementRouteProviderSpec extends WordSpec with ScalatestRouteTest with Matchers {

  val cluster = Cluster(system)

  "Cluster HTTP Management Route" should {
    val routes = ClusterHttpManagementRouteProvider(
      system.asInstanceOf[ExtendedActorSystem]
    )
    "not expose write operations when readOnly set" in {
      val readOnlyRoutes = routes.routes(
        ManagementRouteProviderSettings(
          Uri("http://localhost"),
          readOnly = true
        )
      )
      Get("/cluster/members") ~> readOnlyRoutes ~> check {
        handled shouldEqual true
        status shouldEqual StatusCodes.OK
      }
      Post("/cluster/members") ~> readOnlyRoutes ~> check {
        status shouldEqual StatusCodes.MethodNotAllowed
      }
      Get("/cluster/members/member1") ~> readOnlyRoutes ~> check {
        handled shouldEqual true
        status shouldEqual StatusCodes.NotFound
      }
      Delete("/cluster/members/member1") ~> readOnlyRoutes ~> check {
        status shouldEqual StatusCodes.MethodNotAllowed
      }
      Put("/cluster/members/member1") ~> readOnlyRoutes ~> check {
        status shouldEqual StatusCodes.MethodNotAllowed
      }
    }

    "expose write when readOnly false" in {
      val allRoutes = routes.routes(
        ManagementRouteProviderSettings(
          Uri("http://localhost"),
          readOnly = false
        )
      )
      Get("/cluster/members") ~> allRoutes ~> check {
        handled shouldEqual true
      }
      Get("/cluster/members/member1") ~> allRoutes ~> check {
        handled shouldEqual true
        status shouldEqual StatusCodes.NotFound
      }
      Delete("/cluster/members/member1") ~> allRoutes ~> check {
        handled shouldEqual true
        status shouldEqual StatusCodes.NotFound
      }
      Put("/cluster/members/member1") ~> allRoutes ~> check {
        handled shouldEqual true
        status shouldEqual StatusCodes.NotFound
      }
    }
  }

} 
Example 141
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 142
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 143
Source File: CallService.scala    From microservice-dependency-graph   with MIT License 5 votes vote down vote up
package io.github.rlazoti.servicestats.services

import akka.http.scaladsl.model.StatusCodes
import io.github.rlazoti.servicestats.repositories._
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.server.Directives._
import spray.json._

// Exposes the API endpoint
trait CallService extends CallRepository with EnableCORSDirectives {

  val routes =
    (enableCORS & path("calling") & post & entity(as[ServiceCall])) { call =>
      
      addServiceCalling(call)
      complete(StatusCodes.OK)
    }~
    (enableCORS & path("graphdata") & get) {
      parameters('time) { time =>
        complete(getGraph(time).map(_.toJson))
      }
    }

} 
Example 144
Source File: PaginationDirectivesSpec.scala    From akka-http-extensions   with Apache License 2.0 5 votes vote down vote up
package com.lonelyplanet.akka.http.extensions

import akka.http.scaladsl.model.StatusCodes

class PaginationDirectivesSpec extends PaginationSpec {
  "Pagination" should "not have page if no page is requested" in {
    Get("/filter-test") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual "NoPage"
    }

    Get("/filter-test") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(0, 10, Map.empty).toString
    }
  }

  it should "not have page if page requested have incomplete parameters" in {
    Get("/filter-test?offset=1") ~> paginationRoute ~> check {
      rejection shouldBe a[MalformedPaginationRejection]
    }

    Get("/filter-test?offset=1") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map.empty).toString
    }
  }

  it should "return the page object that was requested" in {
    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }

    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }
  }
} 
Example 145
Source File: PaginationDirectivesWithDefaults.scala    From akka-http-extensions   with Apache License 2.0 5 votes vote down vote up
package com.lonelyplanet.akka.http.extensions

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
import org.scalatest.{FlatSpec, Matchers}

import scala.concurrent.duration.FiniteDuration

class PaginationDirectivesWithDefaults extends PaginationSpec {

  override def testConfigSource =
    """akka.http.extensions.pagination.defaults.enabled = true
      | akka.http.extensions.pagination.defaults.offset = 0
      | akka.http.extensions.pagination.defaults.limit = 50
    """.stripMargin

  "Pagination with defaults" should "not have page if no page is requested" in {

    Get("/filter-test") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] === "NoPage"
    }

    Get("/filter-test") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] === "NoPage"
    }
  }

  it should "have a page with defaults if one of the parameters is set" in {
    Get("/filter-test?offset=1") ~> paginationRoute ~> check {
      responseAs[String] shouldEqual PageRequest(1, 50, Map.empty).toString
    }

    Get("/filter-test?limit=100") ~> paginationRoute ~> check {
      responseAs[String] shouldEqual PageRequest(0, 100, Map.empty).toString
    }

    Get("/filter-test?offset=1") ~> paginationOrDefaultsRoute ~> check {
      responseAs[String] shouldEqual PageRequest(1, 50, Map.empty).toString
    }

    Get("/filter-test?limit=100") ~> paginationOrDefaultsRoute ~> check {
      responseAs[String] shouldEqual PageRequest(0, 100, Map.empty).toString
    }
  }

  it should "return the page object that was requested" in {
    Get("/filter-test?offset=1&limit=10") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map.empty).toString
    }

    Get("/filter-test?offset=1&limit=10") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map.empty).toString
    }
  }

  it should "return the page object with sorting that was requested" in {
    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }

    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }
  }
} 
Example 146
package com.lonelyplanet.akka.http.extensions

import akka.http.scaladsl.model.StatusCodes

class PaginationDirectivesWithDefaultsAndAlwaysFallback extends PaginationSpec {

  override def testConfigSource =
    """akka.http.extensions.pagination.defaults.enabled = true
      | akka.http.extensions.pagination.defaults.always-fallback = true
      | akka.http.extensions.pagination.defaults.offset = 0
      | akka.http.extensions.pagination.defaults.limit = 50
    """.stripMargin

  "Pagination with defaults and fallback" should "have a page with defaults if none was requested" in {

    Get("/filter-test") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(0, 50, Map.empty).toString
    }

    Get("/filter-test") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(0, 50, Map.empty).toString
    }
  }

  it should "have a page with defaults if one of the parameters is set" in {
    Get("/filter-test?offset=1") ~> paginationRoute ~> check {
      responseAs[String] shouldEqual PageRequest(1, 50, Map.empty).toString
    }

    Get("/filter-test?limit=100") ~> paginationRoute ~> check {
      responseAs[String] shouldEqual PageRequest(0, 100, Map.empty).toString
    }

    Get("/filter-test?offset=1") ~> paginationOrDefaultsRoute ~> check {
      responseAs[String] shouldEqual PageRequest(1, 50, Map.empty).toString
    }

    Get("/filter-test?limit=100") ~> paginationOrDefaultsRoute ~> check {
      responseAs[String] shouldEqual PageRequest(0, 100, Map.empty).toString
    }
  }

  it should "return the page object that was requested" in {
    Get("/filter-test?offset=1&limit=10") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map.empty).toString
    }

    Get("/filter-test?offset=1&limit=10") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map.empty).toString
    }
  }

  it should "return the page object with sorting that was requested" in {
    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }

    Get("/filter-test?offset=1&limit=10&sort=name,asc;age,desc") ~> paginationOrDefaultsRoute ~> check {
      status shouldEqual StatusCodes.OK
      responseAs[String] shouldEqual PageRequest(1, 10, Map("name" -> Order.Asc, "age" -> Order.Desc)).toString
    }
  }
} 
Example 147
Source File: AdminError.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.exceptions

import akka.http.scaladsl.model.StatusCodes
import ch.epfl.bluebrain.nexus.commons.http.directives.StatusFrom
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.Contexts._
import ch.epfl.bluebrain.nexus.service.exceptions.ServiceError
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case object InvalidFormat extends AdminError("The json representation is incorrectly formatted.")

  @nowarn("cat=unused")
  implicit val adminErrorEncoder: Encoder[AdminError] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[AdminError].mapJson(_ addContext errorCtxUri)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }

  implicit val adminErrorStatusFrom: StatusFrom[AdminError] = {
    case NotFound             => StatusCodes.NotFound
    case AuthenticationFailed => StatusCodes.Unauthorized
    case AuthorizationFailed  => StatusCodes.Forbidden
    case InvalidFormat        => StatusCodes.BadRequest
    case _                    => StatusCodes.InternalServerError
  }
} 
Example 148
Source File: ElasticSearchBaseClient.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.es.client

import akka.http.scaladsl.model.StatusCodes.GatewayTimeout
import akka.http.scaladsl.model.{HttpRequest, StatusCode, StatusCodes}
import cats.effect.{Effect, Timer}
import cats.implicits._
import ch.epfl.bluebrain.nexus.commons.es.client.ElasticSearchBaseClient._
import ch.epfl.bluebrain.nexus.commons.es.client.ElasticSearchFailure.{ElasticServerError, ElasticUnexpectedError}
import ch.epfl.bluebrain.nexus.commons.http.HttpClient.UntypedHttpClient
import ch.epfl.bluebrain.nexus.sourcing.RetryStrategyConfig
import com.typesafe.scalalogging.Logger
import retry.CatsEffect._
import retry.syntax.all._
import retry.{RetryDetails, RetryPolicy}

import scala.util.control.NonFatal


  private[client] def sanitize(index: String, allowWildCard: Boolean): String = {
    val regex = if (allowWildCard) """[\s|"|\\|<|>|\||,|/|?]""" else """[\s|"|*|\\|<|>|\||,|/|?]"""
    index.replaceAll(regex, "_").dropWhile(_ == '_')
  }
}

object ElasticSearchBaseClient {
  private[client] val docType           = "_doc"
  private[client] val source            = "_source"
  private[client] val anyIndexPath      = "_all"
  private[client] val ignoreUnavailable = "ignore_unavailable"
  private[client] val allowNoIndices    = "allow_no_indices"
  private[client] val trackTotalHits    = "track_total_hits"
} 
Example 149
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 150
Source File: StaticResourceIamAdminRoutesSpec.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.UUID

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes
import org.scalatest.Inspectors
import java.util.regex.Pattern.quote

import ch.epfl.bluebrain.nexus.util.Resources
import com.typesafe.config.{Config, ConfigFactory}
import io.circe.parser.parse
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class StaticResourceIamAdminRoutesSpec
    extends AnyWordSpecLike
    with Matchers
    with Inspectors
    with ScalatestRouteTest
    with Resources {

  val baseUri = "http://nexus.example.com/v1"

  override def testConfig: Config = ConfigFactory.empty()

  val staticRoutes = new StaticResourceRoutes(
    Map(
      "/contexts/context1" -> "/commons/static-routes-test/contexts/context1.json",
      "/contexts/context2" -> "/commons/static-routes-test/contexts/context2.json",
      "/schemas/schema1"   -> "/commons/static-routes-test/schemas/schema1.json",
      "/schemas/schema2"   -> "/commons/static-routes-test/schemas/schema2.json"
    ),
    "test",
    baseUri
  ).routes

  val baseReplacement = Map(
    quote("{{base}}") -> baseUri
  )
  val files           = Map(
    "/v1/test/contexts/context1" -> jsonContentOf(
      "/commons/static-routes-test/contexts/context1.json",
      baseReplacement
    ),
    "/v1/test/contexts/context2" -> jsonContentOf(
      "/commons/static-routes-test/contexts/context2.json",
      baseReplacement
    ),
    "/v1/test/schemas/schema1"   -> jsonContentOf("/commons/static-routes-test/schemas/schema1.json", baseReplacement),
    "/v1/test/schemas/schema2"   -> jsonContentOf("/commons/static-routes-test/schemas/schema2.json", baseReplacement)
  )

  "A StaticResourceRoutes" should {

    "return static resources" in {
      forAll(files.toList) {
        case (path, json) =>
          Get(path) ~> staticRoutes ~> check {
            status shouldEqual StatusCodes.OK
            contentType shouldEqual RdfMediaTypes.`application/ld+json`.toContentType
            parse(responseAs[String]).toOption.get shouldEqual json
          }
      }

    }

    "return 404 when resource doesn't exist" in {
      Get(s"/v1/test/schemas/${UUID.randomUUID().toString}") ~> staticRoutes ~> check {
        rejections shouldEqual Seq()
      }
    }
  }

} 
Example 151
Source File: PrefixDirectivesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.http.directives

import akka.http.scaladsl.model.{StatusCodes, Uri}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.http.directives.PrefixDirectives._
import com.typesafe.config.{Config, ConfigFactory}
import org.scalatest.wordspec.AnyWordSpecLike
import org.scalatest.Inspectors
import org.scalatest.matchers.should.Matchers

class PrefixDirectivesSpec extends AnyWordSpecLike with Matchers with Inspectors with ScalatestRouteTest {

  override def testConfig: Config = ConfigFactory.empty()

  "A PrefixDirective" should {

    "match the prefix uri" in {
      forAll(
        Map(
          ""         -> "",
          "/"        -> "",
          "///"      -> "",
          "/dev"     -> "/dev",
          "/dev/"    -> "/dev",
          "/dev///"  -> "/dev",
          "/dev/sn/" -> "/dev/sn"
        ).toList
      ) {
        case (suffix, prefix) =>
          val uri   = Uri("http://localhost:80" + suffix)
          val route = uriPrefix(uri) {
            path("remainder") {
              get {
                complete(StatusCodes.OK)
              }
            }
          }

          Get(prefix + "/remainder") ~> route ~> check {
            status shouldEqual StatusCodes.OK
          }
      }
    }
  }
} 
Example 152
Source File: ErrorDirectivesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.http.directives

import akka.http.scaladsl.marshalling.Marshal
import akka.http.scaladsl.model.{HttpEntity, HttpResponse, StatusCodes}
import akka.util.ByteString
import ch.epfl.bluebrain.nexus.commons.circe.ContextUri
import ch.epfl.bluebrain.nexus.commons.http.RdfMediaTypes
import ch.epfl.bluebrain.nexus.commons.http.directives.ErrorDirectives._
import ch.epfl.bluebrain.nexus.commons.http.directives.ErrorDirectivesSpec.CustomError
import ch.epfl.bluebrain.nexus.rdf.syntax.iri._
import ch.epfl.bluebrain.nexus.util.ActorSystemFixture
import io.circe.generic.auto._
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

import scala.concurrent.duration._

class ErrorDirectivesSpec
    extends ActorSystemFixture("ErrorDirectivesSpec")
    with AnyWordSpecLike
    with Matchers
    with ScalaFutures {

  implicit override val patienceConfig = PatienceConfig(3.seconds, 100.millis)

  "A ErrorDirectives" should {
    import system.dispatcher
    implicit val statusFromJson: StatusFrom[CustomError] = StatusFrom((_: CustomError) => StatusCodes.NotFound)
    implicit val contextUri: ContextUri                  = ContextUri(url"http://localhost.com/error/")

    "marshall error JSON-LD" in {
      val error      = CustomError("some error")
      val jsonString = s"""{"@context":"${contextUri.value}","message":"${error.message}"}"""
      Marshal(error).to[HttpResponse].futureValue shouldEqual HttpResponse(
        status = StatusCodes.NotFound,
        entity = HttpEntity.Strict(RdfMediaTypes.`application/ld+json`, ByteString(jsonString, "UTF-8"))
      )
    }
  }

}

object ErrorDirectivesSpec {
  final case class CustomError(message: String)
} 
Example 153
Source File: RejectionHandlingSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.commons.http

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Rejection
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.util.EitherValues
import com.typesafe.config.{Config, ConfigFactory}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
import io.circe.{Json, Printer}
import io.circe.parser._
import org.scalatest.Inspectors
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class RejectionHandlingSpec
    extends AnyWordSpecLike
    with Matchers
    with Inspectors
    with ScalatestRouteTest
    with EitherValues {

  class Custom extends Rejection

  override def testConfig: Config       = ConfigFactory.empty()
  implicit private val printer: Printer = Printer.spaces2.copy(dropNullValues = true)

  "A default rejection handler" should {
    val handler =
      RejectionHandling { _: Custom =>
        StatusCodes.InternalServerError -> Json.obj("reason" -> Json.fromString("custom"))
      }.withFallback(RejectionHandling.notFound)

    "handle not found" in {
      val route = handleRejections(handler)(pathEnd(complete("ok")))
      Get("/a") ~> route ~> check {
        val expected =
          s"""{
             |  "@context": "https://bluebrain.github.io/nexus/contexts/error.json",
             |  "@type": "NotFound",
             |  "reason": "The requested resource could not be found."
             |}""".stripMargin
        status shouldEqual StatusCodes.NotFound
        responseAs[Json] shouldEqual parse(expected).rightValue
      }
    }

    "handle missing query param" in {
      val route = handleRejections(handler)(parameter("rev".as[Long])(_ => complete("ok")))
      Get("/a") ~> route ~> check {
        val expected =
          s"""{
             |  "@context": "https://bluebrain.github.io/nexus/contexts/error.json",
             |  "@type": "MissingQueryParam",
             |  "reason": "Request is missing required query parameter 'rev'."
             |}""".stripMargin
        status shouldEqual StatusCodes.BadRequest
        responseAs[Json] shouldEqual parse(expected).rightValue
      }
    }

    "handle custom" in {
      val route = handleRejections(handler)(reject(new Custom))
      Get("/a") ~> route ~> check {
        val expected =
          s"""{
             |  "reason": "custom"
             |}""".stripMargin
        status shouldEqual StatusCodes.InternalServerError
        responseAs[Json] shouldEqual parse(expected).rightValue
      }
    }
  }

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

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
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
import ch.epfl.bluebrain.nexus.kg.routes.EventRoutesSpec.TestableEventRoutes
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import ch.epfl.bluebrain.nexus.rdf.Iri.Path._
import io.circe.Encoder
import monix.eval.Task

class EventRoutesSpec extends EventsSpecBase {

  private val aclsApi = mock[Acls[Task]]
  private val realms  = mock[Realms[Task]]

  val eventRoutes = new TestableEventRoutes(events, aclsApi, realms, caller)

  "EventRoutes" should {
    val read = Permission.unsafe("resources/read")
    aclsApi.hasPermission("org" / "project", read)(caller) shouldReturn Task.pure(true)
    aclsApi.hasPermission(/ + "org", read)(caller) shouldReturn Task.pure(true)

    "return all events for a project" in {
      Get("/") ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(project) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }

    "return all events for an organization" in {
      Get("/") ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for an organization from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> eventRoutes.routes(organization) ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }

}

object EventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
      as: ActorSystem,
      config: ServiceConfig
  ) extends EventRoutes(acls, realms, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 155
Source File: GlobalEventRoutesSpec.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.kg.routes

import akka.NotUsed
import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.headers.`Last-Event-ID`
import akka.http.scaladsl.model.sse.ServerSentEvent
import akka.persistence.query.{EventEnvelope, NoOffset, Offset, Sequence}
import akka.stream.scaladsl.Source
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.kg.resources.Event
import ch.epfl.bluebrain.nexus.kg.routes.GlobalEventRoutesSpec.TestableEventRoutes
import ch.epfl.bluebrain.nexus.rdf.Iri.Path
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig
import io.circe.Encoder
import monix.eval.Task

class GlobalEventRoutesSpec extends EventsSpecBase {

  private val aclsApi = mock[Acls[Task]]
  private val realms  = mock[Realms[Task]]

  val routes = new TestableEventRoutes(events, aclsApi, realms, caller).routes
  aclsApi.hasPermission(Path./, read)(caller) shouldReturn Task.pure(true)

  "GlobalEventRoutes" should {

    "return all events for a project" in {
      Get("/") ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected)
      }
    }

    "return all events for a project from the last seen" in {
      Get("/").addHeader(`Last-Event-ID`(0.toString)) ~> routes ~> check {
        val expected = jsonContentOf("/events/events.json").asArray.value
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual eventStreamFor(expected, 1)
      }
    }
  }
}

object GlobalEventRoutesSpec {

  class TestableEventRoutes(events: List[Event], acls: Acls[Task], realms: Realms[Task], caller: Caller)(implicit
      as: ActorSystem,
      config: ServiceConfig
  ) extends GlobalEventRoutes(acls, realms, caller) {

    private val envelopes = events.zipWithIndex.map {
      case (ev, idx) =>
        EventEnvelope(Sequence(idx.toLong), "persistenceid", 1L, ev, 1L)
    }

    override protected def source(
        tag: String,
        offset: Offset
    )(implicit enc: Encoder[Event]): Source[ServerSentEvent, NotUsed] = {
      val toDrop = offset match {
        case NoOffset    => 0
        case Sequence(v) => v + 1
      }
      Source(envelopes).drop(toDrop).flatMapConcat(ee => Source(eventToSse(ee).toList))
    }
  }
} 
Example 156
Source File: IdentitiesRoutesSpec.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.model.StatusCodes
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.auth.{AccessToken, TokenRejection}
import ch.epfl.bluebrain.nexus.iam.realms._
import ch.epfl.bluebrain.nexus.iam.testsyntax._
import ch.epfl.bluebrain.nexus.iam.types.Caller
import ch.epfl.bluebrain.nexus.iam.types.IamError.InvalidAccessToken
import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Authenticated, User}
import ch.epfl.bluebrain.nexus.service.config.Settings
import ch.epfl.bluebrain.nexus.service.marshallers.instances._
import ch.epfl.bluebrain.nexus.service.routes.Routes
import ch.epfl.bluebrain.nexus.util.Resources
import com.typesafe.config.{Config, ConfigFactory}
import io.circe.Json
import monix.eval.Task
import org.mockito.matchers.MacroBasedMatchers
import org.mockito.{IdiomaticMockito, Mockito}
import org.scalatest.BeforeAndAfter
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

import scala.concurrent.duration._

//noinspection TypeAnnotation
class IdentitiesRoutesSpec
    extends AnyWordSpecLike
    with Matchers
    with ScalatestRouteTest
    with BeforeAndAfter
    with MacroBasedMatchers
    with Resources
    with ScalaFutures
    with IdiomaticMockito {

  implicit override def patienceConfig: PatienceConfig = PatienceConfig(3.seconds, 100.milliseconds)

  override def testConfig: Config = ConfigFactory.load("test.conf")

  private val config        = Settings(system).serviceConfig
  implicit private val http = config.http

  private val realms: Realms[Task] = mock[Realms[Task]]
  private val acls: Acls[Task]     = mock[Acls[Task]]

  before {
    Mockito.reset(realms, acls)
  }

  "The IdentitiesRoutes" should {
    val routes = Routes.wrap(new IdentitiesRoutes(acls, realms).routes)
    "return forbidden" in {
      val err = InvalidAccessToken(TokenRejection.InvalidAccessToken)
      realms.caller(any[AccessToken]) shouldReturn Task.raiseError(err)
      Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check {
        status shouldEqual StatusCodes.Unauthorized
      }
    }
    "return anonymous" in {
      realms.caller(any[AccessToken]) shouldReturn Task.pure(Caller.anonymous)
      Get("/identities") ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[Json].sort shouldEqual jsonContentOf("/identities/anonymous.json")
      }
    }
    "return all identities" in {
      val user   = User("theuser", "therealm")
      val auth   = Authenticated("therealm")
      val caller = Caller(user, Set(user, Anonymous, auth))
      realms.caller(any[AccessToken]) shouldReturn Task.pure(caller)
      Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[Json].sort shouldEqual jsonContentOf("/identities/identities.json")
      }
    }
  }
} 
Example 157
Source File: AuthDirectives.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.StatusCodes
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.server.Directive1
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.directives.FutureDirectives.onComplete
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.{AccessToken, Caller}
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClientError.IdentitiesClientStatusError
import ch.epfl.bluebrain.nexus.storage.StorageError._
import com.typesafe.scalalogging.Logger
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global

import scala.util.{Failure, Success}

object AuthDirectives {

  private val logger = Logger[this.type]

  
  def extractCaller(implicit identities: IamIdentitiesClient[Task], token: Option[AccessToken]): Directive1[Caller] =
    onComplete(identities().runToFuture).flatMap {
      case Success(caller)                                                   => provide(caller)
      case Failure(IdentitiesClientStatusError(StatusCodes.Unauthorized, _)) => failWith(AuthenticationFailed)
      case Failure(IdentitiesClientStatusError(StatusCodes.Forbidden, _))    => failWith(AuthorizationFailed)
      case Failure(err)                                                      =>
        val message = "Error when trying to extract the subject"
        logger.error(message, err)
        failWith(InternalError(message))
    }
} 
Example 158
Source File: StorageError.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.Uri.Path
import ch.epfl.bluebrain.nexus.storage.routes.StatusFrom
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}

import scala.annotation.nowarn


  final case class OperationTimedOut(override val msg: String) extends StorageError(msg)

  @nowarn("cat=unused")
  implicit private val config: Configuration = Configuration.default.withDiscriminator("@type")

  private val derivedEncoder = deriveConfiguredEncoder[StorageError].mapJson(jsonError)

  implicit val storageErrorEncoder: Encoder[StorageError]       =
    Encoder.instance(r => derivedEncoder(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))

  implicit val storageErrorStatusFrom: StatusFrom[StorageError] = {
    case _: PathNotFound      => StatusCodes.NotFound
    case _: PathInvalid       => StatusCodes.BadRequest
    case AuthenticationFailed => StatusCodes.Unauthorized
    case AuthorizationFailed  => StatusCodes.Forbidden
    case _                    => StatusCodes.InternalServerError
  }
} 
Example 159
Source File: Rejection.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.model.Uri.Path
import akka.http.scaladsl.server.{Rejection => AkkaRejection}
import ch.epfl.bluebrain.nexus.storage.routes.StatusFrom
import scala.annotation.nowarn
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveConfiguredEncoder
import io.circe.{Encoder, Json}


  final case class EmptyFilename(name: String)

  implicit def statusCodeFrom: StatusFrom[Rejection] =
    StatusFrom {
      case _: PathContainsLinks => StatusCodes.BadRequest
      case _: PathAlreadyExists => StatusCodes.Conflict
      case _: BucketNotFound    => StatusCodes.NotFound
      case _: PathNotFound      => StatusCodes.NotFound
    }

  @nowarn("cat=unused")
  implicit val rejectionEncoder: Encoder[Rejection] = {
    implicit val rejectionConfig: Configuration = Configuration.default.withDiscriminator("@type")
    val enc                                     = deriveConfiguredEncoder[Rejection].mapJson(jsonError)
    Encoder.instance(r => enc(r) deepMerge Json.obj("reason" -> Json.fromString(r.msg)))
  }
} 
Example 160
Source File: StorageDirectivesSpec.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, Uri}
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.storage.JsonLdCirceSupport._
import ch.epfl.bluebrain.nexus.storage.routes.Routes.exceptionHandler
import ch.epfl.bluebrain.nexus.storage.routes.StorageDirectives._
import ch.epfl.bluebrain.nexus.storage.utils.Resources
import io.circe.Json
import org.scalatest.Inspectors
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

class StorageDirectivesSpec
    extends AnyWordSpecLike
    with Matchers
    with ScalatestRouteTest
    with Inspectors
    with Resources {

  "the storage directives" when {

    def pathInvalidJson(path: Uri.Path): Json =
      jsonContentOf(
        "/error.json",
        Map(
          quote("{type}") -> "PathInvalid",
          quote(
            "{reason}"
          )               -> s"The provided location inside the bucket 'name' with the relative path '$path' is invalid."
        )
      )

    "dealing with file path extraction" should {
      val route = handleExceptions(exceptionHandler) {
        (extractRelativeFilePath("name") & get) { path =>
          complete(s"$path")
        }
      }

      "reject when path contains 2 slashes" in {
        Get("///") ~> route ~> check {
          status shouldEqual StatusCodes.BadRequest
          responseAs[Json] shouldEqual pathInvalidJson(Uri.Path.Empty)
        }
      }

      "reject when path does not end with a segment" in {
        Get("/some/path/") ~> route ~> check {
          status shouldEqual StatusCodes.BadRequest
          responseAs[Json] shouldEqual pathInvalidJson(Uri.Path("some/path/"))
        }
      }

      "return path" in {
        Get("/some/path/file.txt") ~> route ~> check {
          responseAs[String] shouldEqual "some/path/file.txt"
        }
      }
    }

    "dealing with path validation" should {
      def route(path: Uri.Path) =
        handleExceptions(exceptionHandler) {
          (validatePath("name", path) & get) {
            complete(s"$path")
          }
        }

      "reject when some of the segments is . or .." in {
        val paths = List(Uri.Path("/./other/file.txt"), Uri.Path("/some/../file.txt"))
        forAll(paths) { path =>
          Get(path.toString()) ~> route(path) ~> check {
            status shouldEqual StatusCodes.BadRequest
            responseAs[Json] shouldEqual pathInvalidJson(path)
          }
        }
      }

      "pass" in {
        Get("/some/path") ~> route(Uri.Path("/some/path")) ~> check {
          handled shouldEqual true
        }
      }
    }
  }
} 
Example 161
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 162
Source File: BlogRestApi.scala    From akka-blog-example   with Apache License 2.0 5 votes vote down vote up
package com.spr.blog

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server._
import akka.pattern.ask
import com.spr.akka.{AkkaConfiguration, RestApi}

import scala.concurrent.Future


trait BlogRestApi extends RestApi with BlogService {
  override def route: Route =
    pathPrefix("api" / "blog") {
      (pathEndOrSingleSlash & post) {
        // POST /api/blog/
        entity(as[PostContent]) { content =>
          onSuccess(addPost(content)) { added =>
            complete((StatusCodes.Created, added))
          }
        }
      } ~
        pathPrefix(JavaUUID.map(PostId(_))) { id =>
          pathEndOrSingleSlash {
            get {
              // GET /api/blog/:id
              onSuccess(getPost(id)) {
                case Right(content) => complete((StatusCodes.OK, content))
                case Left(error) => complete((StatusCodes.NotFound, error))
              }
            } ~
              put {
                // PUT /api/blog/:id
                entity(as[PostContent]) { content =>
                  onSuccess(updatePost(id, content)) {
                    case Right(updated) => complete((StatusCodes.OK, updated))
                    case Left(error) => complete((StatusCodes.NotFound, error))
                  }
                }
              }
          }
        }
    }
} 
Example 163
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 164
Source File: DownloaderSpec.scala    From CM-Well   with Apache License 2.0 5 votes vote down vote up
package cmwell.tools.data.downloader.streams

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.stream.scaladsl._
import akka.stream.{ActorMaterializer, Materializer}
import akka.util.ByteString
import org.scalatest._
import org.scalatest.prop._

import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.client.WireMock
import com.github.tomakehurst.wiremock.client.WireMock._
import com.github.tomakehurst.wiremock.core.WireMockConfiguration._

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

import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks


class DownloaderSpec extends PropSpec with ScalaCheckPropertyChecks with Matchers with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem("reactive-tools-system")
  implicit val mat: Materializer = ActorMaterializer()
  val host = "localhost"
  val numUuidsPerRequest = 25

  override protected def afterAll(): Unit = {
    system.terminate()
    super.afterAll()
  }

  property ("Download from uuids stream sends request blocks of uuids") {
    val uuids = Table(
      ("numUuids", "blocksToSend"),
      (1         , 1             ),
      (10        , 1             ),
      (20        , 1             ),
      (30        , 2             ),
      (60        , 3             )
    )

    forAll(uuids) { (numUuids: Int, expectedBlocksToSend: Int) =>

      // setup wiremock
      val wireMockServer = new WireMockServer(wireMockConfig().dynamicPort())
      wireMockServer.start()
      val port = wireMockServer.port
      WireMock.configureFor(host, port)

      // create sample uuids to download
      val data = for (x <- 1 to numUuids) yield s"uuid$x\n"

      // wiremock stubbing
      stubFor(post(urlPathMatching("/_out.*"))
        .willReturn(aResponse()
          .withBody("body")
          .withStatus(StatusCodes.OK.intValue)))

      // create uuid input-stream
      val in = Source.fromIterator(() => data.iterator)
        .map(ByteString.apply)
        .runWith(StreamConverters.asInputStream())

      // download mock data
      Await.result (
        Downloader.downloadFromUuidInputStream(
          baseUrl = s"$host:$port",
          numInfotonsPerRequest = numUuidsPerRequest,
          in = in)
        ,30.seconds
      )

      // verifying
      val numBlocksSent = findAll(postRequestedFor((urlPathMatching("/_out.*")))).size

      // teardown wiremock
      wireMockServer.shutdown()
      wireMockServer.stop()
      while (wireMockServer.isRunning) {}
      wireMockServer.resetRequests()

      numBlocksSent should be (expectedBlocksToSend)

    }
  }
} 
Example 165
package io.github.gabfssilva.features

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import io.github.gabfssilva.modules.AllModules
import org.scalatest.{FeatureSpec, Matchers}

class HealthCheckEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest {

  val modules = new AllModules
  val route = modules.endpoints.routes

  feature("health check api") {
    scenario("successful get") {
      Get(s"/api/health-check") ~> route ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "ok"
      }
    }
  }
} 
Example 166
Source File: GreetingEndpointFeature.scala    From akka-http-microservice-templates   with MIT License 5 votes vote down vote up
package io.github.gabfssilva.features

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import io.github.gabfssilva.modules.AllModules
import org.scalatest.{FeatureSpec, Matchers}

class GreetingEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest {

  val modules = new AllModules
  val route = modules.endpoints.routes

  feature("greeting api") {
    scenario("successful get") {
      Get(s"/api/greetings?name=gabriel&greeting=hello") ~> route ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] should include(s"hello, gabriel")
      }
    }

    scenario("unprocessable entity get") {
      Get(s"/api/greetings?name=gabriel&greeting=") ~> route ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }
  }
} 
Example 167
Source File: UserEndpointFeature.scala    From akka-http-microservice-templates   with MIT License 5 votes vote down vote up
package features

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import modules.AllModules
import org.scalatest.{BeforeAndAfterAll, FeatureSpec, Matchers}
import utils.EmbeddedPostgreSQL

class UserEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest
    with BeforeAndAfterAll {

  val modules = new AllModules

  override def beforeAll(): Unit = {
    EmbeddedPostgreSQL.start
  }

  override def afterAll(): Unit = {
    EmbeddedPostgreSQL.stop
  }

  val routes = modules.endpoints.routes

  val httpEntity: (String) => HttpEntity.Strict = (str: String) => HttpEntity(ContentTypes.`application/json`, str)

  feature("user api") {
    scenario("success creation") {
      val validUser =
        """
          {
            "username": "gabfssilva",
            "age": 24
          }
        """

      Post(s"/api/users", httpEntity(validUser)) ~> routes ~> check {
        status shouldBe StatusCodes.Created
      }
    }

    scenario("success get after success creation") {
      val validUser =
        """
          {
            "username": "gabfssilva",
            "age": 24
          }
        """

      Post(s"/api/users", httpEntity(validUser)) ~> routes ~> check {
        status shouldBe StatusCodes.Created

        Get(header("Location").orNull.value()) ~> routes ~> check {
          status shouldBe StatusCodes.OK
        }
      }
    }


    scenario("invalid id on get") {
      Get(s"/api/users/asd") ~> routes ~> check {
        status shouldBe StatusCodes.NotFound
      }
    }

    scenario("no body") {
      Post(s"/api/users", httpEntity("{}")) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }

    scenario("body without age") {
      val invalidUser =
        """
        {
          "username": "gabfssilva"
        }
        """

      Post(s"/api/users", httpEntity(invalidUser)) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }

    scenario("body without username") {
      val invalidUser =
        """
        {
          "age": 24
        }
        """

      Post(s"/api/users", httpEntity(invalidUser)) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }
  }
} 
Example 168
package features

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import modules.AllModules
import org.scalatest.{FeatureSpec, Matchers}

class HealthCheckEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest {

  val modules = new AllModules
  val route = modules.endpoints.routes

  feature("health check api") {
    scenario("successful get") {
      Get(s"/api/health-check") ~> route ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "ok"
      }
    }
  }
} 
Example 169
package features

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import modules.AllModules
import org.scalatest.{FeatureSpec, Matchers}

class HealthCheckEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest {

  val modules = new AllModules
  val route = modules.endpoints.routes

  feature("health check api") {
    scenario("successful get") {
      Get(s"/api/health-check") ~> route ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "ok"
      }
    }
  }
} 
Example 170
Source File: UserEndpointFeature.scala    From akka-http-microservice-templates   with MIT License 5 votes vote down vote up
package features

import akka.http.scaladsl.model.{ContentTypes, HttpEntity, StatusCodes}
import akka.http.scaladsl.testkit.ScalatestRouteTest
import modules.AllModulesTest
import org.scalatest.{BeforeAndAfterAll, FeatureSpec, Matchers}

class UserEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest
    with BeforeAndAfterAll {

  val modules = new AllModulesTest

  val routes = modules.endpoints.routes

  val httpEntity: (String) => HttpEntity.Strict = (str: String) => HttpEntity(ContentTypes.`application/json`, str)

  feature("user api") {
    scenario("success creation") {
      val validUser =
        """
          {
            "username": "gabfssilva",
            "age": 24
          }
        """

      Post(s"/api/users", httpEntity(validUser)) ~> routes ~> check {
        status shouldBe StatusCodes.Created
      }
    }

    scenario("success get after success creation") {
      val validUser =
        """
          {
            "username": "gabfssilva",
            "age": 24
          }
        """

      Post(s"/api/users", httpEntity(validUser)) ~> routes ~> check {
        status shouldBe StatusCodes.Created

        Get(header("Location").orNull.value()) ~> routes ~> check {
          status shouldBe StatusCodes.OK
        }
      }
    }


    scenario("invalid id on get") {
      Get(s"/api/users/1") ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }

    scenario("no body") {
      Post(s"/api/users", httpEntity("{}")) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }

    scenario("body without age") {
      val invalidUser =
        """
        {
          "username": "gabfssilva"
        }
        """

      Post(s"/api/users", httpEntity(invalidUser)) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }

    scenario("body without username") {
      val invalidUser =
        """
        {
          "age": 24
        }
        """

      Post(s"/api/users", httpEntity(invalidUser)) ~> routes ~> check {
        status shouldBe StatusCodes.BadRequest
      }
    }
  }
} 
Example 171
package features

import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import modules.AllModulesTest
import org.scalatest.{FeatureSpec, Matchers}

class HealthCheckEndpointFeature
  extends FeatureSpec
    with Matchers
    with ScalatestRouteTest {

  val modules = new AllModulesTest
  val route = modules.endpoints.routes

  feature("health check api") {
    scenario("successful get") {
      Get(s"/api/health-check") ~> route ~> check {
        status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "ok"
      }
    }
  }
} 
Example 172
Source File: PrometheusUtils.scala    From kafka-lag-exporter   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.kafkalagexporter.integration

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import com.lightbend.kafkalagexporter.MetricsSink.GaugeDefinition
import org.scalatest.Matchers
import org.scalatest.concurrent.ScalaFutures
import org.slf4j.{Logger, LoggerFactory}

import scala.concurrent.{ExecutionContext, Future}
import scala.util.matching.Regex


      val regex = s"""$name\\{$labels.*\\}\\s+(-?.+)""".r
      log.debug(s"Created regex: {}", regex.pattern.toString)
      Rule(regex, assertion)
    }
  }

  case class Rule(regex: Regex, assertion: String => _)

  case class Result(rule: Rule, groupResults: List[String]) {
    def assertDne(): Unit = {
      log.debug(s"Rule: ${rule.regex.toString}")
      groupResults.length shouldBe 0
    }

    def assert(): Unit = {
      log.debug(s"Rule: ${rule.regex.toString}")
      groupResults.length shouldBe 1
      log.debug(s"Actual value is ${groupResults.head}")
      rule.assertion(groupResults.head)
    }
  }
} 
Example 173
Source File: ApplicationStatus.scala    From reactive-lib   with Apache License 2.0 5 votes vote down vote up
package com.lightbend.rp.status

import akka.actor.{ ActorSystem, ExtendedActorSystem, Extension, ExtensionId, ExtensionIdProvider }
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server._
import akka.management.http.{ ManagementRouteProvider, ManagementRouteProviderSettings }
import scala.collection.immutable.Seq
import scala.concurrent.{ ExecutionContext, Future }

import Directives._

class ApplicationStatus(system: ExtendedActorSystem) extends Extension with ManagementRouteProvider {
  private val settings = Settings(system)

  private val healthChecks =
    settings
      .healthChecks
      .map(c =>
        system
          .dynamicAccess
          .createInstanceFor[HealthCheck](c, Seq.empty)
          .getOrElse(throw new IllegalArgumentException(s"Incompatible HealthCheck class definition: $c")))

  private val readinessChecks =
    settings
      .readinessChecks
      .map(c =>
        system
          .dynamicAccess
          .createInstanceFor[ReadinessCheck](c, Seq.empty)
          .getOrElse(throw new IllegalArgumentException(s"Incompatible ReadinessCheck class definition: $c")))

  def routes(settings: ManagementRouteProviderSettings): Route = pathPrefix("platform-tooling") {
    import system.dispatcher

    concat(
      path("ping")(complete("pong!")),
      path("healthy")(complete(isHealthy.map(h => if (h) StatusCodes.OK else StatusCodes.ServiceUnavailable))),
      path("ready")(complete(isReady.map(r => if (r) StatusCodes.OK else StatusCodes.ServiceUnavailable))))
  }

  def isHealthy(implicit ec: ExecutionContext): Future[Boolean] =
    Future
      .sequence(healthChecks.map(_.healthy(system)))
      .map(_.forall(identity))

  def isReady(implicit ec: ExecutionContext): Future[Boolean] =
    Future
      .sequence(readinessChecks.map(_.ready(system)))
      .map(_.forall(identity))
}

object ApplicationStatus extends ExtensionId[ApplicationStatus] with ExtensionIdProvider {
  override def lookup: ApplicationStatus.type = ApplicationStatus
  override def get(system: ActorSystem): ApplicationStatus = super.get(system)
  override def createExtension(system: ExtendedActorSystem): ApplicationStatus = new ApplicationStatus(system)
} 
Example 174
Source File: IdentitiesRoutesSpec.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.model.StatusCodes
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.testkit.ScalatestRouteTest
import ch.epfl.bluebrain.nexus.commons.test.Resources
import ch.epfl.bluebrain.nexus.iam.auth.{AccessToken, TokenRejection}
import ch.epfl.bluebrain.nexus.iam.config.{AppConfig, Settings}
import ch.epfl.bluebrain.nexus.iam.marshallers.instances._
import ch.epfl.bluebrain.nexus.iam.realms._
import ch.epfl.bluebrain.nexus.iam.testsyntax._
import ch.epfl.bluebrain.nexus.iam.types.Caller
import ch.epfl.bluebrain.nexus.iam.types.IamError.InvalidAccessToken
import ch.epfl.bluebrain.nexus.iam.types.Identity.{Anonymous, Authenticated, User}
import com.typesafe.config.{Config, ConfigFactory}
import io.circe.Json
import monix.eval.Task
import org.mockito.matchers.MacroBasedMatchers
import org.mockito.{IdiomaticMockito, Mockito}
import org.scalatest.BeforeAndAfter
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpecLike

import scala.concurrent.duration._

//noinspection TypeAnnotation
class IdentitiesRoutesSpec
    extends AnyWordSpecLike
    with Matchers
    with ScalatestRouteTest
    with BeforeAndAfter
    with MacroBasedMatchers
    with Resources
    with ScalaFutures
    with IdiomaticMockito {

  override implicit def patienceConfig: PatienceConfig = PatienceConfig(3.seconds, 100.milliseconds)

  override def testConfig: Config = ConfigFactory.load("test.conf")

  private val appConfig: AppConfig = Settings(system).appConfig
  private implicit val http        = appConfig.http

  private val realms: Realms[Task] = mock[Realms[Task]]

  before {
    Mockito.reset(realms)
  }

  "The IdentitiesRoutes" should {
    val routes = Routes.wrap(new IdentitiesRoutes(realms).routes)
    "return forbidden" in {
      val err = InvalidAccessToken(TokenRejection.InvalidAccessToken)
      realms.caller(any[AccessToken]) shouldReturn Task.raiseError(err)
      Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check {
        status shouldEqual StatusCodes.Unauthorized
      }
    }
    "return anonymous" in {
      realms.caller(any[AccessToken]) shouldReturn Task.pure(Caller.anonymous)
      Get("/identities") ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[Json].sort shouldEqual jsonContentOf("/identities/anonymous.json")
      }
    }
    "return all identities" in {
      val user   = User("theuser", "therealm")
      val auth   = Authenticated("therealm")
      val caller = Caller(user, Set(user, Anonymous, auth))
      realms.caller(any[AccessToken]) shouldReturn Task.pure(caller)
      Get("/identities").addCredentials(OAuth2BearerToken("token")) ~> routes ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[Json].sort shouldEqual jsonContentOf("/identities/identities.json")
      }
    }
  }
} 
Example 175
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 176
Source File: HttpApiSpec.scala    From jwt-akka-http   with MIT License 5 votes vote down vote up
package ba.codecentric

import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ HttpHeader, StatusCodes }
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.{ Matchers, WordSpec }

class HttpApiSpec extends WordSpec with Matchers with ScalatestRouteTest {
  import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
  import io.circe.generic.auto._
  import HttpApi._

  "HttpApi" should {
    "return 403 Unauthorized upon GET / " in {
      Get() ~> routes ~> check {
        status shouldBe StatusCodes.Unauthorized
      }
    }

    "return 403 Unauthorized when credentials are incorrect" in {
      Post("/", LoginRequest("admin", "something")) ~> routes ~> check {
        header(AccessTokenHeaderName) shouldBe Some(_: HttpHeader)
        status shouldBe StatusCodes.Unauthorized
      }
    }

    "return JWT token upon POST /" in {
      Post("/", LoginRequest("admin", "admin")) ~> routes ~> check {
        header(AccessTokenHeaderName) shouldBe Some(_: HttpHeader)
        status shouldBe StatusCodes.OK
      }
    }

    "access secured content after providing a correct JWT upon GET /" in {
      Post("/", LoginRequest("admin", "admin")) ~> routes ~> check {
        header(AccessTokenHeaderName).map { accessTokenHeader =>
          Get("/").addHeader(RawHeader("Authorization", accessTokenHeader.value())) ~> routes ~> check {
            status shouldBe StatusCodes.OK
          }
        }
      }
    }
  }
} 
Example 177
Source File: StatusRouting.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
import akka.util.Timeout
import cats.effect.IO
import fs2.concurrent.SignallingRef
import vinyldns.api.VinylDNSConfig

import scala.concurrent.duration._

case class CurrentStatus(
    processingDisabled: Boolean,
    color: String,
    keyName: String,
    version: String
)

object CurrentStatus {
  val color = VinylDNSConfig.vinyldnsConfig.getString("color")
  val vinyldnsKeyName = VinylDNSConfig.configuredDnsConnections.defaultZoneConnection.keyName
  val version = VinylDNSConfig.vinyldnsConfig.getString("version")
}

trait StatusRoute extends Directives {
  this: VinylDNSJsonProtocol =>
  import CurrentStatus._

  implicit val timeout = Timeout(10.seconds)

  def processingDisabled: SignallingRef[IO, Boolean]

  val statusRoute =
    (get & path("status")) {
      onSuccess(processingDisabled.get.unsafeToFuture()) { isProcessingDisabled =>
        complete(
          StatusCodes.OK,
          CurrentStatus(isProcessingDisabled, color, vinyldnsKeyName, version)
        )
      }
    } ~
      (post & path("status")) {
        parameters("processingDisabled".as[Boolean]) { isProcessingDisabled =>
          onSuccess(processingDisabled.set(isProcessingDisabled).unsafeToFuture()) {
            complete(
              StatusCodes.OK,
              CurrentStatus(isProcessingDisabled, color, vinyldnsKeyName, version)
            )
          }
        }
      }
} 
Example 178
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 179
Source File: PingRoutingSpec.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class PingRoutingSpec extends AnyWordSpec with ScalatestRouteTest with PingRoute with Matchers {

  def actorRefFactory: ActorSystem = system

  "GET ping" should {
    "return PONG" in {
      Get("/ping") ~> pingRoute ~> check {
        response.status shouldBe StatusCodes.OK
        responseAs[String] shouldBe "PONG"
      }
    }
  }
} 
Example 180
Source File: StatusRoutingSpec.scala    From vinyldns   with Apache License 2.0 5 votes vote down vote up
package vinyldns.api.route

import akka.actor.ActorSystem
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.testkit.ScalatestRouteTest
import cats.effect.{ContextShift, IO}
import fs2.concurrent.SignallingRef
import org.scalatest._
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
import org.scalatestplus.mockito.MockitoSugar

class StatusRoutingSpec
    extends AnyWordSpec
    with ScalatestRouteTest
    with StatusRoute
    with OneInstancePerTest
    with VinylDNSJsonProtocol
    with BeforeAndAfterEach
    with MockitoSugar
    with Matchers {

  def actorRefFactory: ActorSystem = system

  private implicit val cs: ContextShift[IO] =
    IO.contextShift(scala.concurrent.ExecutionContext.global)

  val processingDisabled: SignallingRef[IO, Boolean] =
    fs2.concurrent.SignallingRef[IO, Boolean](false).unsafeRunSync()

  "GET /status" should {
    "return the current status of true" in {
      Get("/status") ~> statusRoute ~> check {
        response.status shouldBe StatusCodes.OK
        val resultStatus = responseAs[CurrentStatus]
        resultStatus.processingDisabled shouldBe false
        resultStatus.color shouldBe "blue"
        resultStatus.keyName shouldBe "vinyldns."
        resultStatus.version shouldBe "unset"
      }
    }
  }

  "POST /status" should {
    "disable processing" in {
      Post("/status?processingDisabled=true") ~> statusRoute ~> check {
        response.status shouldBe StatusCodes.OK
        val resultStatus = responseAs[CurrentStatus]
        resultStatus.processingDisabled shouldBe true
      }
    }

    "enable processing" in {
      Post("/status?processingDisabled=false") ~> statusRoute ~> check {
        response.status shouldBe StatusCodes.OK
        val resultStatus = responseAs[CurrentStatus]
        resultStatus.processingDisabled shouldBe false

        // remember, the signal is the opposite of intent
        processingDisabled.get.unsafeRunSync() shouldBe false
      }
    }
  }
}