8

akka.http新しいライブラリの使い方を理解しようとしています。http 要求をサーバーに送信し、応答本文全体を単一の文字列として読み取り、Source[String,?].

これまでに作成できた最良のソリューションは次のとおりです。

 def get(
   modelID: String,
   pool: Flow[(HttpRequest,Int),(Try[HttpResponse],Int),Http.HostConnectionPool]
 ): Source[String,Unit] = {
   val uri = reactionsURL(modelID)
   val req = HttpRequest(uri = uri)
   Source.single( (req,0) )
     .via( pool )
     .map { 
       case (Success(resp),_) =>
         resp.entity.dataBytes.map( _.decodeString("utf-8") )
     }.flatten(FlattenStrategy.concat)
     .grouped( 1024 )
     .map( _.mkString )

(エラー パスの欠落を除いて) うまく機能しているように見えますが、このような単純なタスクには少し扱いに​​くいです。よりスマートなソリューションはありますか? grouped/を避けることはできますmkStringか?

4

2 に答える 2

11

タイムアウトのあるHttpResponseの toStrict メソッドを使用できます。全体の回答を Future としてまとめます。

def toStrict(timeout: FiniteDuration)(implicit ec: ExecutionContext, fm: Materializer): Future[Strict] 共有可能でシリアライズ可能な

厳密なエンティティを含むこのメッセージのコピー。

例:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.{HttpResponse, HttpRequest}
import akka.stream.{Materializer, ActorMaterializer}
import akka.stream.scaladsl.{Sink, Flow, Source}
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration._

import scala.util.{Try, Success}

object Main extends App {

  implicit val system = ActorSystem()

  import system.dispatcher

  implicit val materializer = ActorMaterializer()

  val host = "127.0.0.1"
  lazy val pool = Http().newHostConnectionPool[Int](host, 9000)

  FlowBuilder.get("/path", pool).to(Sink.foreach(_.foreach(println))).run()

}

object FlowBuilder {
  def get(modelID: String, pool: Flow[(HttpRequest, Int), (Try[HttpResponse], Int), Http.HostConnectionPool])
         (implicit ec: ExecutionContext, mat: Materializer): Source[Future[String], Unit] = {
    val uri = modelID
    val req = HttpRequest(uri = modelID)
    Source.single((req, 0)).via(pool)
      .map { 
      case (Success(resp), _) => resp.entity.toStrict(5 seconds).map(_.data.decodeString("UTF-8")) 
    }
  }
}
于 2015-07-21T07:52:03.910 に答える
7

Unmarshallスプレー json の json など、他のタイプでも動作する which を使用できます。これもstrictリターンとしてFuture[_]

例:

  authedReq.via(authServerReqResFlow).mapAsync(1) { case (tryRes, _) =>
      tryRes match {
        case Failure(exception) => Future.failed[Principal](exception)
        case Success(response @ HttpResponse(StatusCodes.OK,_,_,_)) =>
          val userContext = Unmarshal(response).to[UserContextData]
          userContext.map {
            case UserContextData(UserInfo(_, userName, fullName, email, title), _, _) =>
              Principal(userName, fullName, email, title)
          }
        case Success(response @ HttpResponse(responseCode,_,entity,_)) =>
          Unmarshal(entity).to[String].flatMap(msg => Future.failed(new AuthenticationFailure(s"$responseCode\n$msg")))
      }
    }
于 2015-08-21T22:15:44.443 に答える