如何从akka-stream传播到akka-http的错误都被记录下来并正确通知客户端?

时间:2017-02-16 19:56:02

标签: scala akka-stream akka-http

现在我正在使用akka-streamakka-HTTP来构建文件流API。因此,我将流式源注入实体,以便将数据直接传输到HTTP客户端,如下所示:

complete(HttpEntity(ContentTypes.`application/octet-stream`, source))

但是,如果由于某种原因导致流失败,则连接将被akka-http关闭,无需进一步说明或记录。

我需要两件事:

  • 如何获取例外日志?
  • 如何在关闭连接之前通过消息通知我的客户?

谢谢

1 个答案:

答案 0 :(得分:0)

如评论中所述,HTTP协议不允许向客户端发出错误信号。

关于记录: 对我来说,它归结为缺少akka http中的正确访问日志指令。

在我当前的项目中,我们有装饰器,它在为http实体提供acoka http之前注册onComplete处理程序。

  private def onResponseStreamEnd(response: HttpResponse)(action: StatusCode => Unit): HttpResponse =
    if (!response.status.allowsEntity() || response.entity.isKnownEmpty()) {
      action(response.status)
      response
    } else {
      val dataBytes =
        onStreamEnd(response.entity) { result =>
          val overallStatusCode =
            result match {
              case Success(_) =>
                response.status

              case Failure(e) =>
                logger.error(e, s"error streaming response [${e.getMessage}]")
                StatusCodes.InternalServerError
            }

          action(overallStatusCode)
        }

      response.withEntity(response.entity.contentLengthOption match {
        case Some(length) => HttpEntity(response.entity.contentType, length, dataBytes)
        case None         => HttpEntity(response.entity.contentType, dataBytes)
      })
    }

  private def onStreamEnd(entity: HttpEntity)(onComplete: Try[Done] ⇒ Unit): Source[ByteString, _] =
    entity.dataBytes.alsoTo { Sink.onComplete(onComplete) }

用法:

complete(onResponseStreamEnd(HttpResponse(StatusCodes.OK, HttpEntity(ContentTypes.`application/octet-stream`, source))){ statusCode => .... })

类似的方法,但使用自定义图表阶段,您可以找到here