【问题标题】:Akka http streaming the response headersAkka http 流式传输响应标头
【发布时间】:2018-08-29 11:20:42
【问题描述】:

根据定义,http响应分为3个partsstatus-code -> headers -> body,当做akka客户端http请求时,在前两部分完成后收到http响应 收到了。

  val responseFuture: Future[HttpResponse]
  responseFuture.map {
    case HttpResponse(statusCode:StatusCode, headers:Seq[HttpHeader], entity:ResponseEntity, protocol:HttpProtocol)
  }

这对于大多数用例来说完全没问题,但在我的特殊情况下,我需要在收到所有标头之前访问标头(第三方服务器通过编写自定义进度标头来返回进度,直到响应准备好)。有什么方法可以像访问正文一样访问标题?

  val entity: ResponseEntity
  val entitySource:Source[ByteString, Any] = entity.dataBytes

在完美的世界中,也有一种方法可以将标头作为源访问

HttpResponse(statusCode:StatusCode, headers:Source[HttpHeader, NotUsed], entity:ResponseEntity, protocol:HttpProtocol)

【问题讨论】:

    标签: akka akka-stream akka-http


    【解决方案1】:

    akka-http 不可能

    representation of HttpResponse 将标头视为Seq[HttpHeader],而不是Iteratorakka-stream Source。因此,正如问题中所解释的,如果没有首先提供所有标头值,就不可能实例化 HttpResponse 对象。

    我不知道这个设计决定背后的确切原因,但我怀疑这是因为很难支持标题的 Source 和正文的 Source。如果不首先使用标头 Source,则无法使用正文 Source,因此必须严格按照访问响应的成员变量的顺序。这会导致混乱和意外错误。

    使用akka-stream进行低级处理

    hypertext transfer protocol 只是一个应用层协议,通常在 TCP 之上。而且,它是一个相当simple message format

    响应消息包含以下内容:

    • 包含状态代码和原因消息的状态行(例如, HTTP/1.1 200 OK,表示客户端请求成功)。
    • 响应标头字段(例如,Content-Type: text/html)。
    • 空行。
    • 可选消息正文。

    因此,您可以使用Tcp 绑定来获取连接并解析消息ByteString 自己获取标题:

    val maximumFrameLength = 1024 * 1024
    
    val endOfMessageLine : () => Byte => Boolean = () => {
      var previousWasCarriage = false
    
      (byte) => 
        if(byte == '\r') {
          previousWasCarriage = true
          false
        }
        else if(byte == '\n' && previousWasCarriage) {
          previousWasCarriage = false
          true
        }
        else {
          previousWasCarriage = false
          false
        }
    }
    
    def subFlow = 
      Flow[ByteString].flatMapConcat(str => Source.fromIterable(str))
                      .splitAfter(endOfMessageLine())
    

    不幸的是,这可能还需要通过 Tcp 绑定将您的请求作为原始 ByteString 发送。

    【讨论】:

    • 有道理,我希望我错过了一些神奇的 API,并且不需要回退到 tcp 级别。感谢您解决这个问题!
    猜你喜欢
    • 2022-01-06
    • 2023-04-01
    • 1970-01-01
    • 2018-07-08
    • 2018-02-19
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 2019-06-28
    相关资源
    最近更新 更多