Scala 和 Akka HTTP:如何将实体内容作为字符串获取

Scala and Akka HTTP: How to get the entity content as string

我是 Akka HTTP 的新手,所以对于这个非常初级的问题,请先接受我的道歉。

在下面的代码中,我想从 HTTP 请求中检索实体(实体将是纯文本),从实体中获取文本,然后 return 将其作为响应。

  implicit val system = ActorSystem("ActorSystem")
  implicit val materializer = ActorMaterializer
  import system.dispatcher

  val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].map {
    case HttpRequest(HttpMethods.POST, Uri.Path("/api"), _, entity, _) =>
      val entityAsText = ... // <- get entity content as text

      HttpResponse(
        StatusCodes.OK,
        entity = HttpEntity(
          ContentTypes.`text/plain(UTF-8)`,
          entityAsText
        )
      )
  }

  Http().bindAndHandle(requestHandler, "localhost", 8080)  

如何获取实体的字符串内容?

非常感谢!

一种方法是在 Flow:

上调用 toStrict on the RequestEntity, which loads the entity into memory, and mapAsync
import scala.concurrent.duration._

val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(1) {
  case HttpRequest(HttpMethods.GET, Uri.Path("/api"), _, entity, _) =>
    val entityAsText: Future[String] = entity.toStrict(1 second).map(_.data.utf8String)

    entityAsText.map { text =>
      HttpResponse(
        StatusCodes.OK,
        entity = HttpEntity(
          ContentTypes.`text/plain(UTF-8)`,
          text
        )
      )
    }
}

根据需要调整前者的超时和后者的并行度。

另一种方法是使用已经在范围内的 Unmarshaller(很可能是 akka.http.scaladsl.unmarshalling.PredefinedFromEntityUnmarshallers#stringUnmarshaller):

val entityAsText: Future[String] = Unmarshal(entity).to[String]

这种方法确保提供的 Unmarshaller for String 的一致使用,您不必处理超时问题。