在transformWith [Array [Byte]]内部的“ Future.failed”给出了编译器错误

时间:2019-02-12 21:57:53

标签: scala akka future akka-http jackson-databind

我正在尝试分析Akka的HttpResponse。理想的行为是,如果响应成功返回,则将Array[Byte]的{​​{1}}表示形式传递来进行处理。但是,如果状态作为失败返回,则传递一个带有异常的HttpEntity,其中包含状态代码和Future.failed的JSON树表示形式。传递JSON树的原因是,这种抽象请求方法会攻击不同的服务器,并且它们的响应格式不同,因此我想在其他类中处理响应的解析。

我已经尝试了对该工作流程的各种操作。完全抛出异常而不是返回HttpEntity会返回一个Future.failed值来代替该异常中的JSON树。其他方法产生类似的结果。当我None时,它按我的期望打印出响应,但随后继续在println(MAPPER.readTree(byteArray))的{​​{1}}字段中返回None

response

我期望JsonNode的BadRequestException的值不为零。相反,我在import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers.Authorization import akka.stream.Materializer import com.fasterxml.jackson.databind.{DeserializationFeature, JsonNode, ObjectMapper} import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper val MAPPER = new ObjectMapper with ScalaObjectMapper MAPPER.registerModule(DefaultScalaModule) MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) def performQueryRaw(method: HttpMethod, uri: Uri, entity: Option[RequestEntity] = None, authorization: Option[Authorization] = None): Future[Array[Byte]] = { val request: HttpRequest = HttpRequest( method = method, uri = uri, entity = entity.getOrElse(HttpEntity.Empty), headers = authorization.toList) http.singleRequest(request).transformWith[Array[Byte]] { case Success(response: HttpResponse) => convertEntityToBytes(response.entity).map { byteArray => if (response.status.isFailure()) Future.failed(BadRequestException(response.status, MAPPER.readTree(byteArray))) else byteArray } case Failure(throwable) => Future.failed(RequestFailedException(throwable.getMessage + " -- " + uri.toString, throwable)) } } def convertEntityToBytes(entity: HttpEntity): Future[Array[Byte]] = { entity.dataBytes.runFold[Seq[Array[Byte]]] (Nil) { case (acc, next) => acc :+ next.toArray }.map(_.flatten.toArray) } case class BadRequestException(status: StatusCode, response: JsonNode = None.orNull, t: Throwable = None.orNull) extends Exception(t) case class RequestFailedException(message: String, t: Throwable = None.orNull) extends Exception(message, t) 上遇到了一个编译器错误,内容为:

BadRequestException

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

flatMap之后执行下一步时,请使用map而不是convertEntityToBytes

def performQueryRaw(
    method: HttpMethod,
    uri: Uri,
    entity: Option[RequestEntity] = None,
    authorization: Option[Authorization] = None
  ): Future[Array[Byte]] = {

    val request: HttpRequest = HttpRequest(
      method = method,
      uri = uri,
      entity = entity.getOrElse(HttpEntity.Empty),
      headers = authorization.toList
    )

    Http().singleRequest(request).transformWith[Array[Byte]] {
      case Success(response: HttpResponse) =>
        convertEntityToBytes(response.entity).flatMap { byteArray =>
          if (response.status.isFailure()) Future.failed(new Exception("change this exception to one you had"))
          else Future.successful(byteArray)
        }
      case Failure(throwable) => Future.failed(new Exception("also here"))
    }
  }

由于您无法进行Future计算,因此需要返回新的Future。万一失败,您已经在做Future.failed。缺少的一环也是将byteArray包装到Future.successful。当然,这是解决此代码中的类型编译错误的一种方法。