什么时候在akka-http中实现http响应的内容?

时间:2018-08-09 13:49:44

标签: scala akka akka-stream akka-http

让我们想象一下基于akka-streams和akka-http的代理应用程序,该应用程序以某种本地格式接收(作为TCP服务器)消息,向它们发出http请求,询问其他http服务器,将http响应转换回home-格式增加并回复给客户。下面的简化代码:

// as Client part 
val connPool = Http().cachedHostConnectionPool[CustHttpReq](someHost, somePort)

val asClientFlow = Flow[CustHttpReq]
  .via (connPool)
  .map (procHttpResp)

def procHttpResp (p: (Try[HttpResponse], CustHttpReq)): Future[ByteString] = {
  val (rsp, src) = p
  rsp match {
    case Success(response: HttpResponse) =>
      for (buf <- cvtToHomeGrown (response, src)) 
          yield buf
    case Failure(ex) => ... 
  }
}

def cvtToHomeGrown (rsp: HttpResponse): Future[ByteString] = {
  rsp.entity.dataBytes.runWith (Sink.fold (ByteString.empty)(_ ++ _))
    .map (cvtToHomeGrownActually) // has signature String => ByteString
}

// as Server part
val parseAndAskFlow = Flow[ByteString]
  .via(Framing.delimiter(
    ByteString('\n'))
  .map (buf => cvtToCustHttpReq (buf))
  .via (asClientFlow)  // plug-in asClient part, the problem is here

val asServerConn: Source[IncomingConnection, Future[ServerBinding]] = Tcp().bind("localhost",port)

asServerConn.runForeach (conn => conn.handleWith(parseAndAskFlow)

问题是conn.handleWith需要Flow [ByteString,ByteString,],但是http客户端代码(rsp.entity.dataBytes ...)返回Future [ByteSring],所以parseAndAskFlow的Flow [ByteString,Future [ByteString] ,]类型,但我不知道在哪里可以更好地完成它。我什至认为,就所有这些都是流而言,这根本不是一个好主意,并且等待某处将停止良好的异步处理,但是代码未编译。

1 个答案:

答案 0 :(得分:1)

使用mapAsync而非mapasClientFlow的类型更改为Flow[CustHttpReq, ByteString]

val asClientFlow: Flow[CustHttpReq, ByteString] =
  Flow[CustHttpReq]
    .via(connPool)
    .mapAsync(1)(procHttpResp)

然后,parseAndAskFlow的类型可以为Flow[ByteString, ByteString]

val parseAndAskFlow: Flow[ByteString, ByteString] =
  Flow[ByteString]
    .via(Framing.delimiter(ByteString("\n"))
    .map(cvtToCustHttpReq)
    .via(asClientFlow)