akka.http.scaladsl.server.Directive Scala Examples

The following examples show how to use akka.http.scaladsl.server.Directive. 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: 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 2
Source File: AdminService.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.api

import java.util.UUID

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import akka.http.scaladsl.model.HttpCharsets.`UTF-8`
import akka.http.scaladsl.model.headers.HttpChallenges
import akka.http.scaladsl.server.AuthenticationFailedRejection.CredentialsRejected
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{ AuthenticationFailedRejection, Directive }
import akka.parboiled2.util.Base64
import com.ing.wbaa.rokku.proxy.cache.HazelcastCacheWithConf._
import com.ing.wbaa.rokku.proxy.config.StorageS3Settings
import com.ing.wbaa.rokku.proxy.data.RequestId
import com.typesafe.config.ConfigFactory
import spray.json.DefaultJsonProtocol._

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

trait AdminService {
  protected[this] def storageS3Settings: StorageS3Settings
  protected[this] def setCacheParam(key: String, value: String, map: String = "S3CacheConf")(implicit id: RequestId): Future[Unit]

  case class EligiblePaths(paths: String)
  case class EligibleSize(size: Long)
  case class DownloadTimeout(downloadTimeout: Int)
  case class HeadEnabled(on: Boolean)

  implicit val eligiblePathsF = jsonFormat1(EligiblePaths)
  implicit val eligibleSizeF = jsonFormat1(EligibleSize)
  implicit val downloadTimeoutF = jsonFormat1(DownloadTimeout)
  implicit val headEnabledF = jsonFormat1(HeadEnabled)

  //todo: replace with real authentication
  private val authToken = ConfigFactory.load().getString("rokku.storage.s3.adminToken")
  private def decodeAuthToken(token: String) = new String(Base64.rfc2045.decode(token), `UTF-8`.nioCharset).trim

  private def checkProvidedToken(token: Option[String]) = token match {
    case Some(t) if decodeAuthToken(t) == authToken => true
    case _ => false
  }

  def extractAuthToken: Directive[Tuple1[Option[String]]] =
    optionalHeaderValueByName("AUTH_TOKEN")
      .tflatMap { case Tuple1(v) =>
        checkProvidedToken(v) match {
          case true    => provide(v)
          case false   => reject(AuthenticationFailedRejection(CredentialsRejected, HttpChallenges.basic("Admin API")))
        }
      }
  val adminRoute =
    extractAuthToken { _ =>
      post {
        pathPrefix("api" / "admin") {
          implicit val requestId: RequestId = RequestId(UUID.randomUUID().toString)
          path("allowed" / "paths") {
            entity(as[EligiblePaths]) { conf =>
              onComplete(setCacheParam(ELIGIBLE_CACHE_PATHS, conf.paths)) {
                case Success(_)  => complete(s"Allowed paths - setting updated")
                case Failure(ex) => complete(s"Failed to update configuration parameter: ${ex.getMessage}")
              }
            }
          } ~ path("allowed" / "size") {
            entity(as[EligibleSize]) { conf =>
              onComplete(setCacheParam(MAX_ELIGIBLE_CACHE_OBJECT_SIZE_IN_BYTES, conf.size.toString)) {
                case Success(_)  => complete(s"Allowed size - setting updated")
                case Failure(ex) => complete(s"Failed to update configuration parameter ${ex.getMessage}")
              }
            }
          } ~ path("downloadTimeout") {
            entity(as[DownloadTimeout]) { conf =>
              onComplete(setCacheParam(STRICT_CACHE_DOWNLOAD_TIMEOUT_IN_SECONDS, conf.downloadTimeout.toString)) {
                case Success(_)  => complete(s"downloadTimeout - setting updated")
                case Failure(ex) => complete(s"Failed to update configuration parameter ${ex.getMessage}")
              }
            }
          } ~ path("head" / "on") {
            entity(as[HeadEnabled]) { conf =>
              onComplete(setCacheParam(HEAD_CACHE_ENABLED, conf.on.toString)) {
                case Success(_)  => complete(s"Head on - setting updated")
                case Failure(ex) => complete(s"Failed to update configuration parameter ${ex.getMessage}")
              }
            }
          }
        }
      }
    }
} 
Example 3
Source File: HttpMetricsDirectives.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.ToEntityMarshaller
import akka.http.scaladsl.model.HttpHeader
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.PathMatcher.{Matched, Unmatched}
import akka.http.scaladsl.server.directives.BasicDirectives.{mapRequestContext, tprovide}
import akka.http.scaladsl.server.directives.RouteDirectives.reject
import akka.http.scaladsl.server.util.Tuple
import akka.http.scaladsl.server.{Directive, PathMatcher, StandardRoute}
import fr.davit.akka.http.metrics.core.HttpMetricsRegistry
import fr.davit.akka.http.metrics.core.scaladsl.model.PathLabelHeader

import scala.collection.immutable

trait HttpMetricsDirectives {

  def metrics[T <: HttpMetricsRegistry: ToEntityMarshaller](registry: T): StandardRoute = complete(registry)

  def pathLabeled[L](pm: PathMatcher[L]): Directive[L] =
    pathPrefixLabeled(pm ~ PathEnd)

  def pathLabeled[L](pm: PathMatcher[L], label: String): Directive[L] =
    pathPrefixLabeled(pm ~ PathEnd, label)

  def pathPrefixLabeled[L](pm: PathMatcher[L]): Directive[L] =
    rawPathPrefixLabeled(Slash ~ pm)

  def pathPrefixLabeled[L](pm: PathMatcher[L], label: String): Directive[L] =
    rawPathPrefixLabeled(Slash ~ pm, label)

  def rawPathPrefixLabeled[L](pm: PathMatcher[L]): Directive[L] =
    rawPathPrefixLabeled(pm, None)

  def rawPathPrefixLabeled[L](pm: PathMatcher[L], label: String): Directive[L] =
    rawPathPrefixLabeled(pm, Some(label))

  private def rawPathPrefixLabeled[L](pm: PathMatcher[L], label: Option[String]): Directive[L] = {
    implicit val LIsTuple: Tuple[L] = pm.ev
    extractRequestContext.flatMap { ctx =>
      val pathCandidate = ctx.unmatchedPath.toString
      pm(ctx.unmatchedPath) match {
        case Matched(rest, values) =>
          tprovide(values) & mapRequestContext(_ withUnmatchedPath rest) & mapResponseHeaders { headers =>
            var pathHeader = label match {
              case Some(l) => PathLabelHeader("/" + l) // pm matches additional slash prefix
              case None    => PathLabelHeader(pathCandidate.substring(0, pathCandidate.length - rest.charCount))
            }
            val builder = immutable.Seq.newBuilder[HttpHeader]
            headers.foreach {
              case PathLabelHeader(suffix) =>
                pathHeader = PathLabelHeader(pathHeader.value + suffix)
              case h: HttpHeader =>
                builder += h
            }
            builder += pathHeader
            builder.result()
          }
        case Unmatched =>
          reject
      }
    }
  }
}

object HttpMetricsDirectives extends HttpMetricsDirectives 
Example 4
Source File: BasicAuthentication.scala    From endpoints4s   with MIT License 5 votes vote down vote up
package endpoints4s.akkahttp.server

import akka.http.scaladsl.model.headers.{
  Authorization,
  BasicHttpCredentials,
  HttpChallenges,
  `WWW-Authenticate`
}
import akka.http.scaladsl.model.{HttpHeader, HttpResponse, StatusCodes => AkkaStatusCodes}
import akka.http.scaladsl.server.{Directive, Directive1, Directives}
import endpoints4s.{Tupler, algebra}
import endpoints4s.algebra.BasicAuthentication.Credentials
import endpoints4s.algebra.Documentation


trait BasicAuthentication extends algebra.BasicAuthentication with EndpointsWithCustomErrors {

  private[endpoints4s] def authenticatedRequest[U, E, H, UE, HCred, Out](
      method: Method,
      url: Url[U],
      entity: RequestEntity[E],
      headers: RequestHeaders[H],
      requestDocs: Documentation
  )(implicit
      tuplerUE: Tupler.Aux[U, E, UE],
      tuplerHCred: Tupler.Aux[H, Credentials, HCred],
      tuplerUEHCred: Tupler.Aux[UE, HCred, Out]
  ): Request[Out] = {
    val extractCredentials: HttpHeader => Option[Credentials] = {
      case Authorization(BasicHttpCredentials(username, password)) =>
        Some(Credentials(username, password))
      case _ => None
    }

    val authHeader: Directive1[Credentials] =
      Directives.optionalHeaderValue(extractCredentials).flatMap {
        case Some(credentials) => Directives.provide(credentials)
        case None =>
          Directive[Tuple1[Credentials]] { _ => //inner is ignored
            Directives.complete(
              HttpResponse(
                AkkaStatusCodes.Unauthorized,
                collection.immutable.Seq[HttpHeader](
                  `WWW-Authenticate`(HttpChallenges.basic("Realm"))
                )
              )
            )
          }
      }
    joinDirectives(
      joinDirectives(
        joinDirectives(
          convToDirective1(Directives.method(method)),
          url.directive
        ),
        entity
      ),
      headers ++ authHeader
    )
  }

} 
Example 5
Source File: ValidatingDirectives.scala    From Conseil   with Apache License 2.0 5 votes vote down vote up
package tech.cryptonomic.conseil.api.directives

import akka.http.scaladsl.model.StatusCodes.Unauthorized
import akka.http.scaladsl.server.Directive
import akka.http.scaladsl.server.Directives.{complete, onComplete, optionalHeaderValueByName, provide}
import tech.cryptonomic.conseil.api.security.Security.SecurityApi

import scala.util.Success

class ValidatingDirectives(securityApi: SecurityApi) {

  val validateApiKey: Directive[Tuple1[String]] = optionalHeaderValueByName("apikey").tflatMap[Tuple1[String]] {
    apiKeyTuple =>
      val apiKey = apiKeyTuple match {
        case Tuple1(key) => key
        case _ => None
      }

      onComplete(securityApi.validateApiKey(apiKey)).flatMap {
        case Success(true) => provide(apiKey.getOrElse(""))
        case _ =>
          complete((Unauthorized, apiKey.fold("Missing API key") { _ =>
            "Incorrect API key"
          }))
      }
  }

} 
Example 6
Source File: TextFilesDirectives.scala    From akka-http-extensions   with Mozilla Public License 2.0 5 votes vote down vote up
package akka.http.extensions.resources

import akka.actor.ActorSystem
import akka.http.scaladsl.model.ContentType
import akka.http.scaladsl.server.Directive
import akka.http.scaladsl.server.directives.ContentTypeResolver
import akka.http.scaladsl.server.directives.FileAndResourceDirectives.ResourceFile

trait TextFilesDirectives {

  def resource(resourceName: String,
               classLoader: ClassLoader = classOf[ActorSystem].getClassLoader)
              (implicit resolver: ContentTypeResolver) =  Directive[Tuple1[ResourceFile]]{ inner=>ctx=>
    if (!resourceName.endsWith("/"))
        Option(classLoader.getResource(resourceName)) flatMap ResourceFile.apply match {
          case Some(resource) ⇒  inner(Tuple1(resource))(ctx)
           case other=> ctx.reject()
        }
    else ctx.reject()
  }
} 
Example 7
Source File: ValidationDirectives.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.pattern.validation

import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Directive, ValidationRejection}
import com.wix.accord.{Descriptions, Validator}
import scala.language.implicitConversions

trait ValidationDirectives {
  def validate(magnet: ValidationMagnet) = magnet()
}

object ValidationDirectives extends ValidationDirectives


sealed trait ValidationMagnet {
  def apply(): Directive[Unit]
}

object ValidationMagnet {
  implicit def fromObj[T](obj: T)(implicit validator: Validator[T]) =
    new ValidationMagnet {
      def apply() = {

        val result = com.wix.accord.validate(obj)

        result match {
          case com.wix.accord.Success => pass
          case com.wix.accord.Failure(violations) => reject(
            ValidationRejection(violations map { v => Descriptions.render(v.path) } mkString ", "))
        }
      }
    }
} 
Example 8
Source File: TokenAuthenticator.scala    From akka-http-rest-api   with MIT License 5 votes vote down vote up
package core.authentication

import akka.http.scaladsl.model.headers.HttpChallenge
import akka.http.scaladsl.server.{AuthenticationFailedRejection, Directive, RequestContext}
import redis.RedisClient
import core.authentication.UserSerializer._

import scala.concurrent.ExecutionContext

trait TokenAuthenticator {

  val realm: String = "Private API"

  def authenticate(implicit ec: ExecutionContext, redisClient: RedisClient): Directive[Tuple1[Identity]] = Directive[Tuple1[Identity]] { inner => ctx =>
    getToken(ctx) match {
      case Some(token) =>
        redisClient.get[Identity.User](token).flatMap {
          case Some(value) =>
            inner(Tuple1(Identity(token, value)))(ctx)
          case None => ctx.reject(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsRejected, createChallenge(ctx, Some("Invalid Auth-Token"))))
        }
      case None =>
        ctx.reject(AuthenticationFailedRejection(AuthenticationFailedRejection.CredentialsMissing, createChallenge(ctx, Some("Missing Auth-Token"))))
    }
  }

  private def getToken(ctx: RequestContext): Option[String] = ctx.request.headers.collectFirst {
    case pair if pair.name == "Auth-Token" => pair.value
  }

  private def createChallenge(ctx: RequestContext, message: Option[String]): HttpChallenge = {
    val params = message match {
      case Some(msg) => Map("error" -> "invalid_token", "error_description" -> msg)
      case None => Map.empty[String, String]
    }
    HttpChallenge(ctx.request.getUri().scheme(), realm, params)
  }
} 
Example 9
Source File: catsInstances.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.akkaHttp
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{Directive, Directive1, Rejection, Route}
import cats.{FunctorFilter, Monad, MonoidK}

object catsInstances {
  case object FilterRejection extends Rejection

  implicit val directive1Instance = new Monad[Directive1] with MonoidK[Directive1] with FunctorFilter[Directive1] {
    def pure[A](x: A): Directive1[A]                                                  = provide(x)
    def empty[A]: Directive1[A]                                                       = Directive(_ => reject(FilterRejection))
    def flatMap[A, B](fa: Directive1[A])(f: (A) => Directive1[B]): Directive1[B]      = fa.flatMap(f)
    def tailRecM[A, B](a: A)(f: (A) => Directive1[Either[A, B]]): Directive1[B]       = f(a).flatMap {
      case Left(a1) => tailRecM(a1)(f)
      case Right(x) => pure(x)
    }
    def combineK[A](x: Directive1[A], y: Directive1[A]): Directive1[A]                = x | y
    override def filter[A](fa: Directive1[A])(f: (A) => Boolean): Directive1[A]       = fa.filter(f)
    override def map[A, B](fa: Directive1[A])(f: (A) => B): Directive1[B]             = fa.map(f)
    val functor                                                                       = this
    override def mapFilter[A, B](fa: Directive1[A])(f: A => Option[B]): Directive1[B] =
      Directive(g => fa.tapply { case Tuple1(a) => f(a).fold[Route](reject())(b => g(Tuple1(b))) })
  }
} 
Example 10
Source File: VersionModule.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema
package examples

import akka.http.scaladsl.server.{Directive, Rejection}
import de.heikoseeberger.akkahttpcirce.FailFastCirceSupport._
import ru.tinkoff.tschema.akkaHttp.{MkRoute, Serve}
import ru.tinkoff.tschema.swagger.{SwaggerMapper, _}
import syntax._
import ru.tinkoff.tschema.typeDSL._
import shapeless.{HList, Witness}
import ru.tinkoff.tschema.common.Name

object VersionModule extends ExampleModule {
  def api = tagPrefix("versioned") |> (
    (version("v1") |> get[String]) <>
      (version("v2") |> get[Map[String, Int]]) <>
      (version(Symbol("v2.1")) |> get[Vector[String]])
    )

  object service {
    def v1 = "Ololo"
    def v2 = Map("Olol" -> 0)
    def `v2.1` = Vector("Olo", "lo")
  }

  val route = MkRoute(api)(service)
  val swag = MkSwagger(api)
}

final class version[v] extends DSLAtom

object version {

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

  case class WrongVersionRejection(shouldBe: String, passed: String) extends Rejection

  def apply[v](v: Witness.Aux[v]): version[v] :> Key[v] = new :>

  implicit def versionServe[v : Name, In <: HList]: Serve.Aux[version[v], In, In] = Serve.serveCheck {
    Directive { f =>
      parameter("version") { v =>
        if (v == Name[v].string) f(())
        else reject(WrongVersionRejection(Name[v].string, v))
      } ~
        pathPrefix(Name[v].string) {
          f(())
        }
    }
  }
  implicit def versionSwagger[v: Name]: SwaggerMapper[version[v]] = SwaggerMapper[Prefix[v]].as[version[v]]
} 
Example 11
Source File: ZIODirectives.scala    From full-scala-stack   with Apache License 2.0 5 votes vote down vote up
package api

import akka.http.scaladsl.marshalling.{ Marshaller, Marshalling }
import akka.http.scaladsl.model.HttpResponse
import akka.http.scaladsl.server.{ Directive, Directive1, Route, RouteResult }
import akka.http.scaladsl.marshalling.ToResponseMarshaller
import akka.http.scaladsl.server.directives.RouteDirectives
import akka.http.scaladsl.util.FastFuture._
import zio.{ DefaultRuntime, Task, ZIO }

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


  def zioCompleteOrRecoverWith(magnet: ZIOCompleteOrRecoverWithMagnet): Directive1[Throwable] =
    magnet.directive

}

object ZIODirectives extends ZIODirectives

trait ZIOCompleteOrRecoverWithMagnet {
  def directive: Directive1[Throwable]
}

object ZIOCompleteOrRecoverWithMagnet extends ZIODirectives {
  implicit def apply[T](
    task: => Task[T]
  )(implicit m: ToResponseMarshaller[T]): ZIOCompleteOrRecoverWithMagnet =
    new ZIOCompleteOrRecoverWithMagnet {
      override val directive: Directive1[Throwable] = Directive[Tuple1[Throwable]] { inner => ctx =>
        val future = unsafeRunToFuture(task)
        import ctx.executionContext
        future.fast.transformWith {
          case Success(res)   => ctx.complete(res)
          case Failure(error) => inner(Tuple1(error))(ctx)
        }
      }
    }
}