如何获得akka.http.scaladsl.model.HttpRequest body?
How to get akka.http.scaladsl.model.HttpRequest body?
我正在使用 akka-http
并为我的 类 写一个 Unmarhsaller
。我想要做的是将 POST 请求的主体作为 String
获取,这样我就可以用它创建我的对象:
case class MyClass(geom: String)
implicit def fromRequestUnmarshaller = Unmarshaller[HttpRequest, MyClass]({implicit ec: ExecutionContext =>
req: HttpRequest => Future(MyClass(req.entity.asInstanceOf[HttpEntity.Strict].data.map(_.toChar).mkString))
})
这似乎是一行非常复杂的代码,只是为了将正文作为 String
。另外,我正在做一个非常难看的 asInstanceOf[HttpEntity.Strict]
只是因为我在调试时认为 HttpRequest
是这种类型。
我的问题:是否有 simpler/cleaner 方法来实现我的目标?
非常感谢:)
小心点
akka 将实体实现为 Source[ByteString,_]
的原因是因为 HttpRequest 的实体可能是无限长的。因此,您最好确保您的应用程序有足够的 RAM 来处理可能向其抛出的任何请求...
toStrict
您可以使用 HttpEntity#toStrict
:
implicit val materializer : Materializer = ???
implicit val executionContext : ExecutionContext = ???
val entityFromRequest : (HttpRequest, FiniteDuration) => Future[ByteString] =
(_ : HttpRequest)
.entity
.toStrict(_ : FiniteDuration)
.map(_.data)
手动转换
您可以作为 Source[ByteString, _]
:
访问 HttpRequest 的 "body",即实体
val getBodySource : HttpRequest => Source[ByteString,_] =
_.entity
.dataBytes
然后可以将此 Source 发送到 Sink,后者将 ByteString
值收集到 Seq
:
val convertSrcToSeq : Source[ByteString,_] => Future[Seq[ByteString]] =
_ runWith Sink.seq
您要查找的正文是一个连续的String
,因此这些 ByteString 需要减少为单个值:
val reduceSeqToStr : Future[Seq[ByteString]] => Future[ByteString] =
_ map (_ reduceOption (_ ++ _) getOrElse ByteString.empty)
现在可以将这些步骤组合成一个函数:
val getBodyStrFromRequest : HttpRequest => Future[ByteString] =
getBodySource andThen convertSrcToSeq andThen reduceSeqToStr
我正在使用 akka-http
并为我的 类 写一个 Unmarhsaller
。我想要做的是将 POST 请求的主体作为 String
获取,这样我就可以用它创建我的对象:
case class MyClass(geom: String)
implicit def fromRequestUnmarshaller = Unmarshaller[HttpRequest, MyClass]({implicit ec: ExecutionContext =>
req: HttpRequest => Future(MyClass(req.entity.asInstanceOf[HttpEntity.Strict].data.map(_.toChar).mkString))
})
这似乎是一行非常复杂的代码,只是为了将正文作为 String
。另外,我正在做一个非常难看的 asInstanceOf[HttpEntity.Strict]
只是因为我在调试时认为 HttpRequest
是这种类型。
我的问题:是否有 simpler/cleaner 方法来实现我的目标?
非常感谢:)
小心点
akka 将实体实现为 Source[ByteString,_]
的原因是因为 HttpRequest 的实体可能是无限长的。因此,您最好确保您的应用程序有足够的 RAM 来处理可能向其抛出的任何请求...
toStrict
您可以使用 HttpEntity#toStrict
:
implicit val materializer : Materializer = ???
implicit val executionContext : ExecutionContext = ???
val entityFromRequest : (HttpRequest, FiniteDuration) => Future[ByteString] =
(_ : HttpRequest)
.entity
.toStrict(_ : FiniteDuration)
.map(_.data)
手动转换
您可以作为 Source[ByteString, _]
:
val getBodySource : HttpRequest => Source[ByteString,_] =
_.entity
.dataBytes
然后可以将此 Source 发送到 Sink,后者将 ByteString
值收集到 Seq
:
val convertSrcToSeq : Source[ByteString,_] => Future[Seq[ByteString]] =
_ runWith Sink.seq
您要查找的正文是一个连续的String
,因此这些 ByteString 需要减少为单个值:
val reduceSeqToStr : Future[Seq[ByteString]] => Future[ByteString] =
_ map (_ reduceOption (_ ++ _) getOrElse ByteString.empty)
现在可以将这些步骤组合成一个函数:
val getBodyStrFromRequest : HttpRequest => Future[ByteString] =
getBodySource andThen convertSrcToSeq andThen reduceSeqToStr