akka.http.scaladsl.model.headers.RawHeader Scala Examples

The following examples show how to use akka.http.scaladsl.model.headers.RawHeader. 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: ActionsApiWithDbPollingTests.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller.test

import java.time.Instant

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

import scala.concurrent.duration.DurationInt


  behavior of "Actions API with DB Polling"

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

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

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

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

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

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

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

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{Sink, Source}
import akka.util.ByteString

import scala.collection.immutable
import scala.concurrent.{Future}

object InitIza extends App {

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

  private val http = Http()

  private val features = "http://localhost:9000/api/features"
  //private val features = "http://izanami-perfs.cleverapps.io/api/features"

  Source(0 to 2000)
    .mapAsyncUnordered(10) { postFeature }
    .alsoTo(Sink.foreach {
      case (c, s) if c == StatusCodes.Created =>
      case (c, s) =>
        println(s"Oups $c $s")
    })
    .runWith(Sink.ignore)
    .onComplete { _ =>
      println("Done")
    }

  private def postFeature(i: Int): Future[(StatusCode, String)] = {

    val headers: immutable.Seq[HttpHeader] = immutable.Seq(
      RawHeader("Izanami-Client-Id", "xxxx"),
      RawHeader("Izanami-Client-Secret", "xxxx")
    )

    val body =
      s"""
        | {
        |   "id": "a:key:$i",
        |   "enabled": true,
        |   "activationStrategy": "NO_STRATEGY"
        | }
      """.stripMargin

    http
      .singleRequest(
        HttpRequest(
          HttpMethods.POST,
          Uri(features),
          headers = headers,
          entity = HttpEntity.Strict(ContentTypes.`application/json`, ByteString(body))
        )
      )
      .flatMap {
        case HttpResponse(code, _, entity, _) =>
          entity.dataBytes.map(_.utf8String).runFold("")((str, acc) => str + acc).map(s => (code, s))
      }
  }

} 
Example 3
Source File: RequestDSL.scala    From twitter4s   with Apache License 2.0 5 votes vote down vote up
package com.danielasfregola.twitter4s.helpers

import java.text.SimpleDateFormat
import java.util.Locale

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.testkit.TestProbe
import com.danielasfregola.twitter4s.entities.RateLimit
import org.specs2.specification.AfterEach

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

abstract class RequestDSL extends TestActorSystem with FixturesSupport with AfterEach {

  def after = system.terminate

  private val timeout = 10 seconds

  val headers = List(RawHeader("x-rate-limit-limit", "15"),
                     RawHeader("x-rate-limit-remaining", "14"),
                     RawHeader("x-rate-limit-reset", "1445181993"))

  val rateLimit = {
    val dateFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZZ yyyy", Locale.ENGLISH)
    val resetDate = dateFormatter.parse("Sun Oct 18 15:26:33 +0000 2015").toInstant
    new RateLimit(limit = 15, remaining = 14, reset = resetDate)
  }

  protected val transport = TestProbe()

  def when[T](future: Future[T]): RequestMatcher[T] = new RequestMatcher(future)

  class RequestMatcher[T](future: Future[T]) {
    protected def responder = new Responder(future)

    def expectRequest(req: HttpRequest): Responder[T] = {
      transport.expectMsg(timeout, req)
      responder
    }

    def expectRequest(fn: HttpRequest => Unit) = {
      transport.expectMsgPF(timeout) {
        case req: HttpRequest => fn(req)
      }
      responder
    }
  }

  class Responder[T](future: Future[T]) {
    def respondWith(response: HttpResponse): Await[T] = {
      transport.reply(response)
      new Await(future)
    }

    def respondWith(resourcePath: String): Await[T] =
      respondWith(HttpResponse(StatusCodes.OK, entity = HttpEntity(MediaTypes.`application/json`, load(resourcePath))))

    def respondWithRated(resourcePath: String): Await[T] =
      respondWith(
        HttpResponse(StatusCodes.OK,
                     headers = headers,
                     entity = HttpEntity(MediaTypes.`application/json`, load(resourcePath))))

    def respondWithOk: Await[Unit] = {
      val response =
        HttpResponse(StatusCodes.OK, entity = HttpEntity(MediaTypes.`application/json`, """{"code": "OK"}"""))
      transport.reply(response)
      new Await(Future.successful((): Unit))
    }
  }

  class Await[T](future: Future[T]) {
    private[helpers] val underlyingFuture = future

    def await(implicit duration: FiniteDuration = 20 seconds) =
      Await.result(future, duration)
  }

  implicit def awaitToReqMatcher[T](await: Await[T]) =
    new RequestMatcher(await.underlyingFuture)

} 
Example 4
Source File: RequestContextSpec.scala    From squbs   with Apache License 2.0 5 votes vote down vote up
package org.squbs.pipeline

import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
import akka.testkit.TestKit
import org.scalatest.OptionValues._
import org.scalatest.{BeforeAndAfterAll, FlatSpecLike, Matchers}
import scala.util.Try

class RequestContextSpec
  extends TestKit(ActorSystem("RequestContextSpecSys"))
    with FlatSpecLike
    with Matchers
    with BeforeAndAfterAll {

  override def afterAll(): Unit = {
    system.terminate()
  }

  it should "handle attributes correctly (withAttributes/removeAttributes/expanded variable args)" in {
    val attributeAdditions =
      List(
        "key1" -> "val1",
        "key2" -> 1,
        "key3" -> new Exception("Bad Val")
      )

    val rc1 = RequestContext(HttpRequest(), 0)
    val rc2 = rc1.withAttributes(attributeAdditions:_*)
    rc1.attributes should have size 0
    rc2.attributes should equal(attributeAdditions.toMap)

    val addedKeys = attributeAdditions.map(_._1).toSet
    val removeKeys = Set(addedKeys.head, addedKeys.last)
    val rc3 = rc2.removeAttributes("ibetternotexist" +: removeKeys.toList:_*)
    rc3.attributes.keys.toSet should equal(addedKeys -- removeKeys)
  }

  it should "handle attributes correctly (withAttributes/variable args)" in {
    val rc = RequestContext(HttpRequest(), 0)

    rc.withAttributes(
      "key1" -> "val1",
      "key2" -> 1
    ).attributes should equal(Map("key1" -> "val1", "key2" -> 1))

    rc.attributes should have size 0
  }

  it should "handle attributes correctly (withAttribute/removeAttribute)" in {
    val rc1 = RequestContext(HttpRequest(), 0)

    rc1.attributes should have size 0

    val rc2 = rc1.withAttribute("key1", "val1")
    rc1.attributes should have size 0 // Immutability
    rc2.attribute("key1") should be(Some("val1"))

    val rc3 = rc2.withAttribute("key2", 1).withAttribute("key3", new Exception("Bad Val"))
    rc3.attribute("key2") should be(Some(1))
    rc3.attribute[Exception]("key3").value.getMessage should be("Bad Val")
    rc3.attribute("key1") should be(Some("val1"))

    rc3.attributes should have size 3

    val rc4 = rc3.removeAttribute("key1")
    rc3.attributes should have size 3 // Immutability
    rc4.attributes should have size 2

    val rc5 = rc4.removeAttribute("notexists")
    rc5.attributes should have size 2
    rc5.attribute("key2") should be(Some(1))
    rc5.attribute[Exception]("key3").value.getMessage should be("Bad Val")
  }

  it should "handle headers correctly" in {
    val rc1 = RequestContext(HttpRequest(), 0)
    val rc2 = rc1.withRequestHeader(RawHeader("key1", "val1"))
    val rc3 = rc2.withRequestHeaders(RawHeader("key2", "val2"), RawHeader("key3", "val3"))

    rc3.request.headers should have size 3
    rc3.response should be(None)
    rc3.request.headers should contain(RawHeader("key1", "val1"))

    val rc4 = rc3.withResponse(Try(HttpResponse()))
    rc4.response.value.get.headers should have size 0
    val rc5 = rc4.withResponseHeader(RawHeader("key4", "val4"))
    val rc6 = rc5.withResponseHeaders(RawHeader("key5", "val5"), RawHeader("key6", "val6"))
    val rc7 = rc6.withResponseHeader(RawHeader("key7", "val7"))
    rc7.request.headers should have size 3
    rc7.response.value.get.headers should have size 4
    rc7.response.value.get.headers should contain(RawHeader("key4", "val4"))
  }

} 
Example 5
Source File: HeaderUtils.scala    From asura   with MIT License 5 votes vote down vote up
package asura.core.http

import akka.http.scaladsl.model.HttpHeader.ParsingResult.{Error, Ok}
import akka.http.scaladsl.model.headers.{Cookie, RawHeader}
import akka.http.scaladsl.model.{ErrorInfo, HttpHeader}
import asura.common.util.StringUtils
import asura.core.es.model.{Environment, HttpCaseRequest}
import asura.core.runtime.RuntimeContext
import asura.core.{CoreConfig, ErrorMessages}
import com.typesafe.scalalogging.Logger

import scala.collection.immutable
import scala.collection.mutable.ArrayBuffer

object HeaderUtils {

  val logger = Logger("HeaderUtils")

  def toHeaders(cs: HttpCaseRequest, context: RuntimeContext): immutable.Seq[HttpHeader] = {
    val headers = ArrayBuffer[HttpHeader]()
    val request = cs.request
    val env = if (null != context.options) context.options.getUsedEnv() else null
    if (null != request) {
      val headerSeq = request.header
      if (null != headerSeq) {
        for (h <- headerSeq if (h.enabled && StringUtils.isNotEmpty(h.key))) {
          HttpHeader.parse(h.key, context.renderSingleMacroAsString(h.value)) match {
            case Ok(header: HttpHeader, errors: List[ErrorInfo]) =>
              if (errors.nonEmpty) logger.warn(errors.mkString(","))
              headers += header
            case Error(error: ErrorInfo) =>
              logger.warn(error.detail)
          }
        }
      }
      val cookieSeq = request.cookie
      if (null != cookieSeq) {
        val cookies = ArrayBuffer[(String, String)]()
        for (c <- cookieSeq if (c.enabled && StringUtils.isNotEmpty(c.key))) {
          cookies += ((c.key, context.renderSingleMacroAsString(c.value)))
        }
        if (cookies.nonEmpty) headers += Cookie(cookies: _*)
      }
    }
    if (null != env && null != env.headers && env.headers.nonEmpty) {
      for (h <- env.headers if (h.enabled && StringUtils.isNotEmpty(h.key))) {
        HttpHeader.parse(h.key, context.renderSingleMacroAsString(h.value)) match {
          case Ok(header: HttpHeader, errors: List[ErrorInfo]) =>
            if (errors.nonEmpty) logger.warn(errors.mkString(","))
            headers += header
          case Error(error: ErrorInfo) =>
            logger.warn(error.detail)
        }
      }
    }
    if (null != env && env.enableProxy) {
      val headerIdentifier = validateProxyVariables(env)
      val dst = StringBuilder.newBuilder
      dst.append("/").append(cs.group).append("/").append(cs.project).append("/").append(env.namespace)
      headers += RawHeader(headerIdentifier, dst.toString)
    }
    headers.toList
  }

  def validateProxyVariables(env: Environment): String = {
    if (!CoreConfig.linkerdConfig.enabled) {
      throw ErrorMessages.error_ProxyDisabled.toException
    }
    if (StringUtils.isEmpty(env.namespace)) {
      throw ErrorMessages.error_EmptyNamespace.toException
    }
    if (StringUtils.isEmpty(env.server)) {
      throw ErrorMessages.error_EmptyProxyServer.toException
    }
    val proxyServerOpt = CoreConfig.linkerdConfig.servers.find(_.tag.equals(env.server))
    if (proxyServerOpt.isEmpty && StringUtils.isEmpty(proxyServerOpt.get.headerIdentifier)) {
      throw ErrorMessages.error_InvalidProxyConfig.toException
    } else {
      proxyServerOpt.get.headerIdentifier
    }
  }

  def isApplicationJson(header: HttpHeader): Boolean = {
    if (header.lowercaseName().equals("content-type")) {
      header.value().contains(HttpContentTypes.JSON)
    } else {
      false
    }
  }
} 
Example 6
Source File: BasicAuth.scala    From asura   with MIT License 5 votes vote down vote up
package asura.app.api.auth

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

import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.headers.RawHeader
import asura.core.auth.AuthorizeAndValidate
import asura.core.es.model.Authorization

import scala.concurrent.Future

object BasicAuth extends AuthorizeAndValidate {

  override val `type`: String = "Basic Auth"
  override val description: String =
    """## Basic Auth
      |> Add a header with the key `Authorization` and the value a string encoded by base64.
      |
      |### Example
      |
      |If the data is as below:
      |
      |```json
      |{
      |    "username" : "a",
      |    "password": "b"
      |}
      |```
      |
      |A header `Authorization: Basic YTpi` will be added. `YTpi` is generated by call `Base64.encode("a:b")`.
      |
    """.stripMargin


  override val template: String =
    """{
      |    "username" : "",
      |    "password": ""
      |}
    """.stripMargin

  override def authorize(request: HttpRequest, auth: Authorization): Future[HttpRequest] = {
    val username = auth.data.get("username")
    val password = auth.data.get("password")
    val bytes = Base64.getEncoder.encode(s"${username.get}:${password.get}".getBytes(StandardCharsets.UTF_8))
    val value = new String(bytes, StandardCharsets.UTF_8)
    Future.successful(request.withHeaders(request.headers :+ RawHeader("Authorization", s"Basic ${value}")))
  }

  override def validate(auth: Authorization): (Boolean, String) = {
    val username = auth.data.get("username")
    val password = auth.data.get("password")
    if (username.isEmpty || password.isEmpty) {
      (false, "username and password can't be empty")
    } else {
      (true, null)
    }
  }
} 
Example 7
Source File: GrpcEntityHelpers.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package akka.grpc.internal

import akka.NotUsed
import akka.actor.{ ActorSystem, ClassicActorSystemProvider }
import akka.annotation.InternalApi
import akka.grpc.{ GrpcServiceException, ProtobufSerializer, Trailers }
import akka.grpc.GrpcProtocol.{ DataFrame, Frame, GrpcProtocolWriter, TrailerFrame }
import akka.grpc.scaladsl.{ headers, BytesEntry, Metadata, StringEntry }
import akka.http.scaladsl.model.HttpEntity.ChunkStreamPart
import akka.http.scaladsl.model.HttpHeader
import akka.http.scaladsl.model.headers.RawHeader
import akka.stream.scaladsl.Source
import io.grpc.Status


@InternalApi
object GrpcEntityHelpers {
  def apply[T](
      e: Source[T, NotUsed],
      trail: Source[TrailerFrame, NotUsed],
      eHandler: ActorSystem => PartialFunction[Throwable, Trailers])(
      implicit m: ProtobufSerializer[T],
      writer: GrpcProtocolWriter,
      system: ClassicActorSystemProvider): Source[ChunkStreamPart, NotUsed] = {
    chunks(e, trail).recover {
      case t =>
        val e = eHandler(system.classicSystem).orElse[Throwable, Trailers] {
          case e: GrpcServiceException => Trailers(e.status, e.metadata)
          case e: Exception            => Trailers(Status.UNKNOWN.withCause(e).withDescription("Stream failed"))
        }(t)
        writer.encodeFrame(trailer(e.status, e.metadata))
    }
  }

  def apply[T](e: T)(implicit m: ProtobufSerializer[T], writer: GrpcProtocolWriter): Source[ChunkStreamPart, NotUsed] =
    chunks(Source.single(e), Source.empty)

  private def chunks[T](e: Source[T, NotUsed], trail: Source[Frame, NotUsed])(
      implicit m: ProtobufSerializer[T],
      writer: GrpcProtocolWriter): Source[ChunkStreamPart, NotUsed] =
    e.map { msg => DataFrame(m.serialize(msg)) }.concat(trail).via(writer.frameEncoder)

  def trailer(status: Status): TrailerFrame =
    TrailerFrame(trailers = statusHeaders(status))

  def trailer(status: Status, metadata: Metadata): TrailerFrame =
    TrailerFrame(trailers = statusHeaders(status) ++ metadataHeaders(metadata))

  def statusHeaders(status: Status): List[HttpHeader] =
    List(headers.`Status`(status.getCode.value.toString)) ++ Option(status.getDescription).map(d =>
      headers.`Status-Message`(d))

  def metadataHeaders(metadata: Metadata): List[HttpHeader] =
    metadata.asList.map {
      case (key, StringEntry(value)) => RawHeader(key, value)
      case (key, BytesEntry(value))  => RawHeader(key, MetadataImpl.encodeBinaryHeader(value))
    }
} 
Example 8
Source File: ErrorReportingSpec.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package example.myapp.helloworld

import akka.actor.ActorSystem
import akka.grpc.internal.GrpcProtocolNative
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.HttpEntity.{ Chunked, LastChunk }
import akka.http.scaladsl.model.headers.RawHeader
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import example.myapp.helloworld.grpc.{ GreeterService, GreeterServiceHandlerFactory }
import io.grpc.Status
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.Span
import org.scalatest.BeforeAndAfterAll
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

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

class ErrorReportingSpec extends AnyWordSpec with Matchers with ScalaFutures with BeforeAndAfterAll {
  implicit val sys = ActorSystem()
  override implicit val patienceConfig = PatienceConfig(5.seconds, Span(100, org.scalatest.time.Millis))

  "A gRPC server" should {
    implicit val mat = ActorMaterializer()

    val handler = GreeterServiceHandlerFactory.create(new GreeterServiceImpl(mat), sys)
    val binding = {
      import akka.http.javadsl.{ ConnectHttp, Http }

      Http(sys).bindAndHandleAsync(handler, ConnectHttp.toHost("127.0.0.1", 0), mat).toCompletableFuture.get
    }

    "respond with an 'unimplemented' gRPC error status when calling an unknown method" in {
      val request = HttpRequest(
        method = HttpMethods.POST,
        entity = HttpEntity.empty(GrpcProtocolNative.contentType),
        uri = s"http://localhost:${binding.localAddress.getPort}/${GreeterService.name}/UnknownMethod")
      val response = Http().singleRequest(request).futureValue

      response.status should be(StatusCodes.OK)
      allHeaders(response) should contain(RawHeader("grpc-status", Status.Code.UNIMPLEMENTED.value().toString))
    }

    "respond with an 'invalid argument' gRPC error status when calling an method without a request body" in {
      val request = HttpRequest(
        method = HttpMethods.POST,
        entity = HttpEntity.empty(GrpcProtocolNative.contentType),
        uri = s"http://localhost:${binding.localAddress.getPort}/${GreeterService.name}/SayHello")
      val response = Http().singleRequest(request).futureValue

      response.status should be(StatusCodes.OK)
      allHeaders(response) should contain(RawHeader("grpc-status", Status.Code.INVALID_ARGUMENT.value().toString))
    }

    def allHeaders(response: HttpResponse) =
      response.entity match {
        case Chunked(_, chunks) =>
          chunks.runWith(Sink.last).futureValue match {
            case LastChunk(_, trailingHeaders) => response.headers ++ trailingHeaders
            case _                             => response.headers
          }
        case _ =>
          response.headers
      }
  }

  override def afterAll: Unit =
    Await.result(sys.terminate(), 5.seconds)
} 
Example 9
Source File: ErrorReportingSpec.scala    From akka-grpc   with Apache License 2.0 5 votes vote down vote up
package example.myapp.helloworld

import akka.actor.{ ActorSystem, ClassicActorSystemProvider }
import akka.grpc.internal.GrpcProtocolNative
import akka.http.scaladsl.model.HttpEntity.{ Chunked, LastChunk }
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.{ Http, HttpConnectionContext }
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import example.myapp.helloworld.grpc.{ GreeterService, GreeterServiceHandler }
import io.grpc.Status
import org.junit.runner.RunWith
import org.scalatest.BeforeAndAfterAll
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.matchers.should.Matchers
import org.scalatest.time.Span
import org.scalatest.wordspec.AnyWordSpec
import org.scalatestplus.junit.JUnitRunner

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

@RunWith(classOf[JUnitRunner])
class ErrorReportingSpec extends AnyWordSpec with Matchers with ScalaFutures with BeforeAndAfterAll {

  override implicit val patienceConfig = PatienceConfig(5.seconds, Span(100, org.scalatest.time.Millis))

  implicit val system: ActorSystem = ActorSystem()

  implicit val mat = ActorMaterializer()

  "A gRPC server" should {

    val binding = Http()
      .bindAndHandleAsync(
        GreeterServiceHandler(new GreeterServiceImpl())(system.asInstanceOf[ClassicActorSystemProvider]),
        interface = "127.0.0.1",
        port = 0,
        connectionContext = HttpConnectionContext())
      .futureValue

    "respond with an 'unimplemented' gRPC error status when calling an unknown method" in {
      val request = HttpRequest(
        method = HttpMethods.POST,
        entity = HttpEntity.empty(GrpcProtocolNative.contentType),
        uri = s"http://localhost:${binding.localAddress.getPort}/${GreeterService.name}/UnknownMethod")
      val response = Http().singleRequest(request).futureValue

      response.status should be(StatusCodes.OK)
      allHeaders(response) should contain(RawHeader("grpc-status", Status.Code.UNIMPLEMENTED.value().toString))
    }

    "respond with an 'invalid argument' gRPC error status when calling an method without a request body" in {
      val request = HttpRequest(
        method = HttpMethods.POST,
        entity = HttpEntity.empty(GrpcProtocolNative.contentType),
        uri = s"http://localhost:${binding.localAddress.getPort}/${GreeterService.name}/SayHello")
      val response = Http().singleRequest(request).futureValue

      response.status should be(StatusCodes.OK)
      allHeaders(response) should contain(RawHeader("grpc-status", Status.Code.INVALID_ARGUMENT.value().toString))
    }

    def allHeaders(response: HttpResponse) =
      response.entity match {
        case Chunked(_, chunks) =>
          chunks.runWith(Sink.last).futureValue match {
            case LastChunk(_, trailingHeaders) => response.headers ++ trailingHeaders
            case _                             => response.headers
          }
        case _ =>
          response.headers
      }
  }

  override def afterAll: Unit =
    Await.result(system.terminate(), 5.seconds)
} 
Example 10
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 11
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 12
Source File: Issue184.scala    From guardrail   with MIT License 5 votes vote down vote up
package core.issues

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.http.scaladsl.unmarshalling.Unmarshaller
import cats.instances.future._
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.SpanSugar._
import org.scalatest.{ EitherValues, FunSuite, Matchers }
import scala.concurrent.Future
import io.circe._


    Delete("/1234?query=2345")
      .withEntity(
        Multipart
          .FormData(
            Multipart.FormData.BodyPart.Strict("form", "3456")
          )
          .toEntity
      ) ~> route ~> check {
      response.status shouldBe (StatusCodes.NoContent)
    }
  }
} 
Example 13
Source File: Issue121.scala    From guardrail   with MIT License 5 votes vote down vote up
package core.issues

import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.server._
import akka.http.scaladsl.testkit.ScalatestRouteTest
import akka.http.scaladsl.unmarshalling.Unmarshaller
import cats.instances.future._
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.time.SpanSugar._
import org.scalatest.{ EitherValues, FunSuite, Matchers }
import scala.concurrent.Future
import io.circe._

class Issue121Suite extends FunSuite with Matchers with EitherValues with ScalaFutures with ScalatestRouteTest {
  override implicit val patienceConfig = PatienceConfig(10 seconds, 1 second)

  test("akka-http server can respond with 204") {
    import issues.issue121.server.akkaHttp.{ Handler, Resource }
    val route = Resource.routes(new Handler {
      override def deleteFoo(respond: Resource.DeleteFooResponse.type)(id: Long): Future[Resource.DeleteFooResponse] =
        Future.successful(respond.NoContent)
    })

    Delete("/entity").withEntity(FormData("id" -> "1234").toEntity) ~> route ~> check {
      status should equal(StatusCodes.NoContent)
      response.entity.contentType should equal(ContentTypes.NoContentType)
      response.entity.contentLengthOption should equal(Some(0))
    }
  }

  test("akka-http client can respond with 204") {
    import issues.issue121.client.akkaHttp.Client

    def noContentResponse: HttpRequest => Future[HttpResponse] = _ => Future.successful(HttpResponse(204))

    
    Client
      .httpClient(noContentResponse, "http://localhost:80")
      .deleteFoo(1234)
      .fold(
        _ => failTest("Error"),
        _.fold(
          handleNoContent = ()
        )
      )
      .futureValue
  }
} 
Example 14
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 15
Source File: HttpClient.scala    From heimdallr   with Apache License 2.0 5 votes vote down vote up
package chat

import scala.util.{Failure, Success, Try}
import akka.actor._
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import akka.stream.ActorMaterializer
import akka.util.ByteString
import scala.concurrent.{ExecutionContext, Future}
import chat.HttpClient._
import UserActor.CustomResponse

object HttpClient {
  case class HttpClientGet(event: String, path : String)
  case class HttpClientPost(event: String, path : String, token: String, jsonBody: String)
  case class HttpClientResponseSuccess(event: String, resHttp: HttpResponse, recipient: ActorRef)
  case class HttpClientResponseFailure(event: String, reason: String, recipient: ActorRef)
}

class HttpClient()(implicit system: ActorSystem, mat: ActorMaterializer, dispatcher: ExecutionContext)
  extends Actor with ActorLogging {

  def pipeToSelf(event: String, future: Future[HttpResponse], recipient: ActorRef): Future[HttpResponse] = {
    future andThen {
      case Success(r) => self ! HttpClientResponseSuccess(event, r, recipient)
      case Failure(f) => self ! HttpClientResponseFailure(event, f.toString, recipient)
    }
  }

  def post(event: String, path: String, token: String, jsonBody: String, recipient: ActorRef) = {
    val objectEntity = HttpEntity(ContentTypes.`application/json`, jsonBody)
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(
      method = HttpMethods.POST,
      uri = path,
      entity = objectEntity
      ).withHeaders(
        RawHeader("Authorization", "Token " + token)
      )
    )

    pipeToSelf(event, responseFuture, recipient)

  }

  def get(event: String, path: String, recipient:ActorRef) = {
    val responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(
      method = HttpMethods.GET,
      uri = path
      )
    )

    pipeToSelf(event, responseFuture, recipient)
  }

  def receive = {
    case HttpClientGet(event, path) =>
      get(event, path, sender)

    case HttpClientPost(event, path, token, jsonBody) =>
      post(event, path, token, jsonBody, sender)

    // connection success
    case HttpClientResponseSuccess(event, resp, recipient) =>
      resp match {
        case HttpResponse(StatusCodes.OK, headers, entity, _) =>
          entity.dataBytes.runFold(ByteString(""))(_ ++ _).foreach { body =>
            log.info("Got response, body: " + body.utf8String)
            recipient ! CustomResponse(event, 200, body.utf8String)
          }

        case resp @ HttpResponse(code, _, _, _) =>
          log.info("Request failed, response code: " + code)
          resp.discardEntityBytes()
          recipient ! CustomResponse(event, code.intValue(), s"Request failed, response code: $code")
      }

    // connection failure
    case HttpClientResponseFailure(event, resp, recipient) =>
      log.info("Request failed, reason: " + resp)
      recipient ! CustomResponse(event, 599, s"Request failed, response code: ${resp}")

    case x =>
      log.info(s"HttpClient Request failed: ${x}")
  }

  override def preStart(): Unit = {
  }

  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    preStart()
  }

  override def postRestart(reason: Throwable): Unit = {
    log.info( reason.toString )
  }

  override def postStop(): Unit = {
  }
} 
Example 16
Source File: Entities.scala    From openwhisk   with Apache License 2.0 5 votes vote down vote up
package org.apache.openwhisk.core.controller

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

protected[controller] trait ValidateRequestSize extends Directives {

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

  
  protected final def isEntity(n: String) = Try { EntityName(n) } isSuccess
} 
Example 17
Source File: Registry.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando.kanadi.api

import java.net.URI

import defaults._
import akka.http.scaladsl.HttpExt
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ContentTypes, HttpMethods, HttpRequest, Uri}
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.stream.Materializer
import com.typesafe.scalalogging.{Logger, LoggerTakingImplicit}
import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport._
import org.mdedetrich.webmodels.{FlowId, OAuth2TokenProvider}
import org.mdedetrich.webmodels.RequestHeaders.`X-Flow-ID`
import org.zalando.kanadi.models._

import scala.concurrent.{ExecutionContext, Future}

case class Registry(baseUri: URI, oAuth2TokenProvider: Option[OAuth2TokenProvider] = None)(implicit
                                                                                           kanadiHttpConfig: HttpConfig,
                                                                                           http: HttpExt,
                                                                                           materializer: Materializer)
    extends RegistryInterface {
  protected val logger: LoggerTakingImplicit[FlowId] = Logger.takingImplicit[FlowId](classOf[Registry])
  private val baseUri_                               = Uri(baseUri.toString)

  
  def partitionStrategies(implicit flowId: FlowId = randomFlowId(),
                          executionContext: ExecutionContext): Future[List[PartitionStrategy]] = {
    val uri =
      baseUri_.withPath(baseUri_.path / "registry" / "partition-strategies")

    val baseHeaders = List(RawHeader(`X-Flow-ID`, flowId.value))

    for {
      headers <- oAuth2TokenProvider match {
                  case None => Future.successful(baseHeaders)
                  case Some(futureProvider) =>
                    futureProvider.value().map { oAuth2Token =>
                      toHeader(oAuth2Token) +: baseHeaders
                    }
                }
      request  = HttpRequest(HttpMethods.GET, uri, headers)
      _        = logger.debug(request.toString)
      response <- http.singleRequest(request)
      result <- {
        if (response.status.isSuccess()) {
          Unmarshal(response.entity.httpEntity.withContentType(ContentTypes.`application/json`))
            .to[List[PartitionStrategy]]
        } else
          processNotSuccessful(request, response)
      }
    } yield result
  }

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

import java.time.Instant

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

import scala.concurrent.duration.DurationInt


  behavior of "Actions API without DB Polling"

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

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

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

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

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

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

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

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

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

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

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

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

} 
Example 19
Source File: ClientCredentialsStrategy.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.strategy

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model._
import akka.stream.scaladsl.Source
import com.github.dakatsuka.akka.http.oauth2.client.{ ConfigLike, GrantType }

class ClientCredentialsStrategy extends Strategy(GrantType.ClientCredentials) {
  override def getAuthorizeUrl(config: ConfigLike, params: Map[String, String] = Map.empty): Option[Uri] = None

  override def getAccessTokenSource(config: ConfigLike, params: Map[String, String] = Map.empty): Source[HttpRequest, NotUsed] = {
    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.tokenUrl))

    val request = HttpRequest(
      method = config.tokenMethod,
      uri = uri,
      headers = List(
        RawHeader("Accept", "*/*")
      ),
      FormData(
        params ++ Map(
          "grant_type"    -> grant.value,
          "client_id"     -> config.clientId,
          "client_secret" -> config.clientSecret
        )
      ).toEntity(HttpCharsets.`UTF-8`)
    )

    Source.single(request)
  }
} 
Example 20
Source File: AuthorizationCodeStrategy.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.strategy

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model._
import akka.stream.scaladsl.Source
import com.github.dakatsuka.akka.http.oauth2.client.{ ConfigLike, GrantType }

class AuthorizationCodeStrategy extends Strategy(GrantType.AuthorizationCode) {
  override def getAuthorizeUrl(config: ConfigLike, params: Map[String, String] = Map.empty): Option[Uri] = {
    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.authorizeUrl))
      .withQuery(Uri.Query(params ++ Map("response_type" -> "code", "client_id" -> config.clientId)))

    Option(uri)
  }

  override def getAccessTokenSource(config: ConfigLike, params: Map[String, String] = Map.empty): Source[HttpRequest, NotUsed] = {
    require(params.contains("code"))
    require(params.contains("redirect_uri"))

    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.tokenUrl))

    val request = HttpRequest(
      method = config.tokenMethod,
      uri = uri,
      headers = List(
        RawHeader("Accept", "*/*")
      ),
      FormData(
        params ++ Map(
          "grant_type"    -> grant.value,
          "client_id"     -> config.clientId,
          "client_secret" -> config.clientSecret
        )
      ).toEntity(HttpCharsets.`UTF-8`)
    )

    Source.single(request)
  }
} 
Example 21
Source File: RefreshTokenStrategy.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.strategy

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ FormData, HttpCharsets, HttpRequest, Uri }
import akka.stream.scaladsl.Source
import com.github.dakatsuka.akka.http.oauth2.client.{ ConfigLike, GrantType }

class RefreshTokenStrategy extends Strategy(GrantType.RefreshToken) {
  override def getAuthorizeUrl(config: ConfigLike, params: Map[String, String] = Map.empty): Option[Uri] = None

  override def getAccessTokenSource(config: ConfigLike, params: Map[String, String] = Map.empty): Source[HttpRequest, NotUsed] = {
    require(params.contains("refresh_token"))

    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.tokenUrl))

    val request = HttpRequest(
      method = config.tokenMethod,
      uri = uri,
      headers = List(
        RawHeader("Accept", "*/*")
      ),
      FormData(
        params ++ Map(
          "grant_type"    -> grant.value,
          "client_id"     -> config.clientId,
          "client_secret" -> config.clientSecret
        )
      ).toEntity(HttpCharsets.`UTF-8`)
    )

    Source.single(request)
  }
} 
Example 22
Source File: PasswordCredentialsStrategy.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.strategy

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model._
import akka.stream.scaladsl.Source
import com.github.dakatsuka.akka.http.oauth2.client.{ ConfigLike, GrantType }

class PasswordCredentialsStrategy extends Strategy(GrantType.PasswordCredentials) {
  override def getAuthorizeUrl(config: ConfigLike, params: Map[String, String] = Map.empty): Option[Uri] = None

  override def getAccessTokenSource(config: ConfigLike, params: Map[String, String] = Map.empty): Source[HttpRequest, NotUsed] = {
    require(params.contains("username"))
    require(params.contains("password"))

    val uri = Uri
      .apply(config.site.toASCIIString)
      .withPath(Uri.Path(config.tokenUrl))

    val request = HttpRequest(
      method = config.tokenMethod,
      uri = uri,
      headers = List(
        RawHeader("Accept", "*/*")
      ),
      FormData(
        params ++ Map(
          "grant_type"    -> grant.value,
          "client_id"     -> config.clientId,
          "client_secret" -> config.clientSecret
        )
      ).toEntity(HttpCharsets.`UTF-8`)
    )

    Source.single(request)
  }
} 
Example 23
Source File: LineageHelperSpec.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.provider

import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.headers.RawHeader
import com.ing.wbaa.rokku.proxy.config.KafkaSettings
import com.ing.wbaa.rokku.proxy.data.{ BucketClassification, DirClassification, ObjectClassification, RequestId }
import com.ing.wbaa.rokku.proxy.provider.atlas.LineageHelpers
import org.scalatest.PrivateMethodTester
import org.scalatest.diagrams.Diagrams
import org.scalatest.wordspec.AnyWordSpec

import scala.concurrent.ExecutionContext

class LineageHelperSpec extends AnyWordSpec with Diagrams with PrivateMethodTester {

  object LineageHelpersTest extends LineageHelpers {
    override protected[this] implicit val kafkaSettings: KafkaSettings = null
    override protected[this] implicit val executionContext: ExecutionContext = null
  }

  implicit val id = RequestId("1")

  "extractMetadataFromHeader" that {
    "return None for empty header" in {
      val result = LineageHelpersTest.extractMetadataHeader(None)
      assert(result.isEmpty)
    }

    "return None for wrong header" in {
      val result = LineageHelpersTest.extractMetadataHeader(Some("k,v"))
      assert(result.isEmpty)
      val result2 = LineageHelpersTest.extractMetadataHeader(Some("k=v,k2"))
      assert(result2.isEmpty)
      val result3 = LineageHelpersTest.extractMetadataHeader(Some("kv,=k2,v2"))
      assert(result3.isEmpty)
    }

    "return key and value for metadata header" in {
      val result = LineageHelpersTest.extractMetadataHeader(Some("k=v"))
      assert(result.contains(Map("k" -> "v")))
    }

    "return keys and values for metadata header" in {
      val result = LineageHelpersTest.extractMetadataHeader(Some("k1=v1,k2=v2"))
      assert(result.contains(Map("k1" -> "v1", "k2" -> "v2")))
    }
  }

  "extractClassifications" that {
    "returns bucket classifications" in {
      val request = HttpRequest().withUri("bucket").withHeaders(RawHeader(LineageHelpersTest.CLASSIFICATIONS_HEADER, "classification1"))
      val result = LineageHelpersTest.extractClassifications(request)
      assert(result.size == 1)
      assert(result contains BucketClassification())
      assert(result(BucketClassification()) == List("classification1"))
    }

    "returns dir classifications" in {
      val request = HttpRequest().withUri("bucket/dir1/").withHeaders(RawHeader(LineageHelpersTest.CLASSIFICATIONS_HEADER, "classification1,classification2"))
      val result = LineageHelpersTest.extractClassifications(request)
      assert(result.size == 1)
      assert(result contains DirClassification())
      assert(result(DirClassification()) == List("classification1", "classification2"))
    }

    "returns object classifications" in {
      val request = HttpRequest().withUri("bucket/obj").withHeaders(RawHeader(LineageHelpersTest.CLASSIFICATIONS_HEADER, "classification1,classification2,classification3"))
      val result = LineageHelpersTest.extractClassifications(request)
      assert(result.size == 1)
      assert(result contains ObjectClassification())
      assert(result(ObjectClassification()) == List("classification1", "classification2", "classification3"))
      val request2 = HttpRequest().withUri("bucket/dir1/obj").withHeaders(RawHeader(LineageHelpersTest.CLASSIFICATIONS_HEADER, "classification1"))
      val result2 = LineageHelpersTest.extractClassifications(request2)
      assert(result2.size == 1)
      assert(result2 contains ObjectClassification())
      assert(result2(ObjectClassification()) == List("classification1"))
    }
  }

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

import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model._
import akka.stream.scaladsl.Source
import akka.util.ByteString

object CacheHelpers {

  private val headerSeparator = "::"
  private val objSeparator = "|"
  val isHead: HttpRequest => Boolean = request => request.method == HttpMethods.HEAD

  def processHeadersForCache(headers: Seq[HttpHeader], contentLength: Option[Long], statusCode: StatusCode): String = {
    val originalHeaders = headers.map(r => s"${r.name()}$headerSeparator${r.value()}")
    contentLength match {
      case Some(cl) => Seq(statusCode.intValue()) ++ originalHeaders ++ Seq(RawHeader("ContentLength:", cl.toString))
      case None     => Seq(statusCode.intValue()) ++ originalHeaders
    }
  }.mkString(objSeparator)

  def processHeadersFromCache(bs: Option[ByteString]): (StatusCode, List[RawHeader]) = {
    bs.map { b =>
      {
        val params = b.utf8String.split(s"\\$objSeparator")
        (
          StatusCode.int2StatusCode(params(0).toInt),
          params.drop(1)
          .map { pair =>
            pair.split(headerSeparator).grouped(2)
              .map { arr =>
                RawHeader(arr(0), arr(1))
              }
          }.toList.flatten)
      }
    }.get
  }

  // https://github.com/akka/akka-http/issues/377
  // return a pseudo Default entity that contains the content-length and an Empty data stream
  def generateFakeEntity(contentLength: Long): ResponseEntity = {
    val entityWithSize: Long => HttpEntity.Default = cl =>
      HttpEntity.Default(
        ContentType.WithMissingCharset(MediaTypes.`text/plain`),
        cl,
        Source(ByteString() :: Nil)
      )

    if (contentLength == 0) {
      HttpEntity.Empty
    } else {
      entityWithSize(contentLength)
    }
  }
}

sealed class CacheValueObject

case class HeadCacheValueObject(headers: Seq[HttpHeader], contentLength: Option[Long], statusCode: StatusCode) extends CacheValueObject

case class GetCacheValueObject(data: ByteString) extends CacheValueObject 
Example 26
Source File: RequestHandlerS3.scala    From rokku   with Apache License 2.0 5 votes vote down vote up
package com.ing.wbaa.rokku.proxy.handler

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.RawHeader
import com.ing.wbaa.rokku.proxy.config.StorageS3Settings
import com.ing.wbaa.rokku.proxy.data.{ RequestId, S3Request, User }
import com.ing.wbaa.rokku.proxy.handler.exception.RokkuThrottlingException
import com.ing.wbaa.rokku.proxy.handler.radosgw.RadosGatewayHandler
import com.ing.wbaa.rokku.proxy.provider.aws.S3Client
import com.ing.wbaa.rokku.proxy.queue.UserRequestQueue

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

trait RequestHandlerS3 extends RadosGatewayHandler with S3Client with UserRequestQueue {

  private val logger = new LoggerHandlerWithId

  protected[this] implicit def system: ActorSystem

  protected[this] implicit def executionContext: ExecutionContext

  protected[this] def storageS3Settings: StorageS3Settings

  protected[this] def filterResponse(request: HttpRequest, userSTS: User, s3request: S3Request, response: HttpResponse)(implicit id: RequestId): HttpResponse

  
  protected[this] def fireRequestToS3(request: HttpRequest, user: User)(implicit id: RequestId): Future[HttpResponse] = {
    if (storageS3Settings.isRequestUserQueueEnabled) {
      if (addIfAllowedUserToRequestQueue(user)) {
        fireRequestToS3(request).andThen { case _ => decrement(user) }
      } else {
        implicit val returnStatusCode: StatusCodes.ServerError = StatusCodes.ServiceUnavailable
        logger.warn("user {} is sending too many requests", user.userName.value)
        Future.failed(new RokkuThrottlingException("Throttling"))
      }
    } else {
      fireRequestToS3(request)
    }
  }
} 
Example 27
Source File: RequestHandlerS3Cache.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._
import akka.http.scaladsl.model.headers.RawHeader
import akka.stream.ActorMaterializer
import akka.util.ByteString
import com.ing.wbaa.rokku.proxy.cache.{ CacheRulesV1, HazelcastCacheWithConf }
import com.ing.wbaa.rokku.proxy.data.RequestId
import com.ing.wbaa.rokku.proxy.handler.parsers.CacheHelpers._
import com.ing.wbaa.rokku.proxy.handler.parsers.{ GetCacheValueObject, HeadCacheValueObject }
import com.ing.wbaa.rokku.proxy.handler.parsers.RequestParser.AWSRequestType

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

trait RequestHandlerS3Cache extends HazelcastCacheWithConf with RequestHandlerS3 with CacheRulesV1 {

  private val logger = new LoggerHandlerWithId
  implicit val materializer: ActorMaterializer

  def awsRequestFromRequest(request: HttpRequest): AWSRequestType

  def isEligibleToBeCached(request: HttpRequest)(implicit id: RequestId): Boolean

  def isEligibleToBeInvalidated(request: HttpRequest)(implicit id: RequestId): Boolean

  override protected[this] def fireRequestToS3(request: HttpRequest)(implicit id: RequestId): Future[HttpResponse] = {

    if (storageS3Settings.isCacheEnabled) {
      if (isEligibleToBeCached(request)) {
        getObjectFromCacheOrStorage(request)
      } else {
        invalidateEntryIfObjectInCache(request)
        super.fireRequestToS3(request)
      }
    } else {
      super.fireRequestToS3(request)
    }
  }

  
  private def readFromStorageAndUpdateCache(request: HttpRequest)(implicit id: RequestId): Future[Unit] = {
    Future {
      val key = getKey(request)
      super.fireRequestToS3(request).flatMap { response =>

        if (isHead(request)) {
          response.entity.discardBytes()
          Future.successful(HeadCacheValueObject(response.headers, response.entity.contentLengthOption, response.status))
        } else if (isEligibleSize(response)) {
          //todo: add head request to reduce amount of get's
          response.entity.toStrict(getStrictCacheDownloadTimeoutInSeconds.seconds, getMaxEligibleCacheObjectSizeInBytes).flatMap { r =>
            r.dataBytes.runFold(ByteString.empty) { case (acc, b) => acc ++ b }
          }.map(bs => GetCacheValueObject(bs))
        } else {
          response.entity.discardBytes()
          Future.failed(new ObjectTooBigException())
        }
      }.onComplete {
        case Failure(exception: ObjectTooBigException) => logger.debug("Object too big to be stored in cache {}", key, exception)
        case Failure(exception)                        => logger.error("Cannot store object () in cache {}", key, exception)
        case Success(headValue: HeadCacheValueObject) =>
          val value = processHeadersForCache(headValue.headers, headValue.contentLength, headValue.statusCode)
          logger.debug("head object cache value {} for key {}", value, key)
          putObject(key, ByteString(value))
        case Success(getValue: GetCacheValueObject) => putObject(key, getValue.data)
      }
    }
  }

  class ObjectTooBigException extends Exception

} 
Example 28
Source File: ClickhouseQueryBuilder.scala    From clickhouse-scala-client   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package com.crobox.clickhouse.internal

import akka.http.scaladsl.model.Uri.Query
import akka.http.scaladsl.model.headers.{HttpEncodingRange, RawHeader}
import akka.http.scaladsl.model.{HttpMethods, HttpRequest, RequestEntity, Uri}
import com.crobox.clickhouse.internal.QuerySettings.ReadQueries
import com.crobox.clickhouse.internal.progress.ProgressHeadersAsEventsStage
import com.typesafe.config.Config
import com.typesafe.scalalogging.LazyLogging

import scala.collection.immutable

private[clickhouse] trait ClickhouseQueryBuilder extends LazyLogging {

  private val Headers = {
    import HttpEncodingRange.apply
    import akka.http.scaladsl.model.headers.HttpEncodings.{deflate, gzip}
    import akka.http.scaladsl.model.headers.`Accept-Encoding`
    immutable.Seq(`Accept-Encoding`(gzip, deflate))
  }
  private val MaxUriSize = 16 * 1024

  protected def toRequest(uri: Uri,
                          query: String,
                          queryIdentifier: Option[String],
                          settings: QuerySettings,
                          entity: Option[RequestEntity])(config: Config): HttpRequest = {
    val urlQuery = uri.withQuery(Query(Query("query" -> query) ++ settings.withFallback(config).asQueryParams: _*))
    entity match {
      case Some(e) =>
        logger.debug(s"Executing clickhouse query [$query] on host [${uri
          .toString()}] with entity payload of length ${e.contentLengthOption}")
        HttpRequest(
          method = HttpMethods.POST,
          uri = urlQuery,
          entity = e,
          headers = Headers ++ queryIdentifier.map(RawHeader(ProgressHeadersAsEventsStage.InternalQueryIdentifier, _))
        )
      case None
          if settings.idempotent.contains(true) && settings.readOnly == ReadQueries && urlQuery
            .toString()
            .getBytes
            .length < MaxUriSize => //max url size
        logger.debug(s"Executing clickhouse idempotent query [$query] on host [${uri.toString()}]")
        HttpRequest(
          method = HttpMethods.GET,
          uri = urlQuery.withQuery(
            urlQuery
              .query()
              .filterNot(
                _._1 == "readonly"
              ) //get requests are readonly by default, if we send the readonly flag clickhouse will fail the request
          ),
          headers = Headers ++ queryIdentifier.map(RawHeader(ProgressHeadersAsEventsStage.InternalQueryIdentifier, _))
        )
      case None =>
        logger.debug(s"Executing clickhouse query [$query] on host [${uri.toString()}]")
        HttpRequest(
          method = HttpMethods.POST,
          uri = uri.withQuery(settings.withFallback(config).asQueryParams),
          entity = query,
          headers = Headers ++ queryIdentifier.map(RawHeader(ProgressHeadersAsEventsStage.InternalQueryIdentifier, _))
        )
    }
  }

} 
Example 29
Source File: GitHubSpec.scala    From akka-api-gateway-example   with MIT License 5 votes vote down vote up
package jp.co.dzl.example.akka.api.service

import akka.actor.ActorSystem
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ HttpMethods, HttpRequest, HttpResponse }
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.{ Flow, Source }
import akka.stream.testkit.scaladsl.TestSink
import org.scalamock.scalatest.MockFactory
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.{ BeforeAndAfterAll, FlatSpec, Matchers }

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

class GitHubSpec extends FlatSpec with Matchers with ScalaFutures with BeforeAndAfterAll with MockFactory {
  implicit val system = ActorSystem("github-spec")
  implicit val executor = system.dispatcher
  implicit val materializer = ActorMaterializer()

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

  "#from" should "merge original headers to github request" in {
    val github = new GitHubImpl("127.0.0.1", 8000, 5, mock[HttpClient])
    val request = HttpRequest(HttpMethods.GET, "/")
      .addHeader(RawHeader("host", "dummy"))
      .addHeader(RawHeader("timeout-access", "dummy"))

    val result = Source.single(HttpRequest(HttpMethods.GET, "/v1/github/users/xxxxxx"))
      .via(github.from(request))
      .runWith(TestSink.probe[HttpRequest])
      .request(1)
      .expectNext()

    result.headers.filter(_.lowercaseName() == "host") shouldBe empty
    result.headers.filter(_.lowercaseName() == "timeout-access") shouldBe empty
    result.headers.filter(_.lowercaseName() == "x-forwarded-host") shouldNot be(empty)
  }

  "#send" should "connect using http client" in {
    val httpResponse = HttpResponse()
    val httpClient = mock[HttpClient]
    (httpClient.connectionHttps _).expects(*, *, *).returning(Flow[HttpRequest].map(_ => httpResponse))

    val github = new GitHubImpl("127.0.0.1", 8000, 5, httpClient)
    val result = Source.single(HttpRequest(HttpMethods.GET, "/"))
      .via(github.send)
      .runWith(TestSink.probe[HttpResponse])
      .request(1)
      .expectNext()

    result shouldBe httpResponse
  }
} 
Example 30
Source File: GitHub.scala    From akka-api-gateway-example   with MIT License 5 votes vote down vote up
package jp.co.dzl.example.akka.api.service

import akka.NotUsed
import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ HttpRequest, HttpResponse }
import akka.stream.scaladsl.Flow

trait GitHub {
  def from(original: HttpRequest): Flow[HttpRequest, HttpRequest, NotUsed]
  def send: Flow[HttpRequest, HttpResponse, NotUsed]
}

class GitHubImpl(
    host:       String,
    port:       Int,
    timeout:    Int,
    httpClient: HttpClient
) extends GitHub {
  def from(original: HttpRequest): Flow[HttpRequest, HttpRequest, NotUsed] = Flow[HttpRequest].map { req =>
    val xForwardedHost = original.headers.find(_.is("host")).map(_.value()).getOrElse(s"$host:$port")
    val modifiedHeader = original.addHeader(RawHeader("X-Forwarded-Host", xForwardedHost))
      .headers
      .filterNot(_.lowercaseName() == "host")
      .filterNot(_.lowercaseName() == "timeout-access")

    req.withHeaders(modifiedHeader)
  }

  def send: Flow[HttpRequest, HttpResponse, NotUsed] =
    Flow[HttpRequest].via(httpClient.connectionHttps(host, port, timeout))
} 
Example 31
Source File: S2GraphTraversalRoute.scala    From incubator-s2graph   with Apache License 2.0 5 votes vote down vote up
package org.apache.s2graph.http

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

object S2GraphTraversalRoute {

  import scala.collection._

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

trait S2GraphTraversalRoute extends PlayJsonSupport {

  import S2GraphTraversalRoute._

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

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

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

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

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

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

  // expose routes
  lazy val traversalRoute: Route =
    post {
      concat(
        delegated // getEdges, experiments, etc.
      )
    }
}