Scala 和 Akka HTTP:处理表单数据请求
Scala and Akka HTTP: Processing form-data requests
假设我们有以下请求:
curl --location --request POST 'localhost:8080/api' \
--header 'Content-Type: multipart/form-data' \
--form 'field1=value1' \
--form 'field2=value2'
下面的请求处理程序获取了整个实体,但我正在努力寻找如何获取 value1
和 value2
.
val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(1) {
case HttpRequest(HttpMethods.POST, Uri.Path("/api"), _, entity, _) =>
val entityTextFuture: Future[String] = entity.toStrict(3 seconds).map(_.data.utf8String)
entityTextFuture.flatMap { text =>
Future(HttpResponse(
StatusCodes.OK,
entity = text
))
}
}
重要:我必须使用Akka HTTP低级服务器API,所以我不能使用路由。
非常感谢您抽出宝贵时间提前提供帮助!
如果您只需要表单数据中的字符串值,您只需解组为 StrictForm
,然后将每个字段值解组为字符串。
这是一个概念验证 Ammonite 脚本,它使用 value1 & value2
:
响应您的 curl 请求
import $ivy.`com.typesafe.akka::akka-actor:2.6.3`
import $ivy.`com.typesafe.akka::akka-stream:2.6.3`
import $ivy.`com.typesafe.akka::akka-http:10.1.11`
import scala.concurrent.Future
import akka.actor.ActorSystem
import akka.stream.scaladsl.Flow
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.common.StrictForm
implicit val system = ActorSystem()
implicit val ec = system.dispatcher
val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(1) {
case HttpRequest(HttpMethods.POST, Uri.Path("/api"), _, entity, _) =>
for {
strictForm <- Unmarshal(entity).to[StrictForm]
fieldsSeq <- Future.traverse(strictForm.fields) {
case (n, v) => Unmarshal(v).to[String].map(n -> _)
}
fields = fieldsSeq.toMap
response = fields("field1") + " & " + fields("field2")
} yield HttpResponse(StatusCodes.OK, entity = response)
}
Http().bindAndHandle(requestHandler, "localhost", 8080)
假设我们有以下请求:
curl --location --request POST 'localhost:8080/api' \
--header 'Content-Type: multipart/form-data' \
--form 'field1=value1' \
--form 'field2=value2'
下面的请求处理程序获取了整个实体,但我正在努力寻找如何获取 value1
和 value2
.
val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(1) {
case HttpRequest(HttpMethods.POST, Uri.Path("/api"), _, entity, _) =>
val entityTextFuture: Future[String] = entity.toStrict(3 seconds).map(_.data.utf8String)
entityTextFuture.flatMap { text =>
Future(HttpResponse(
StatusCodes.OK,
entity = text
))
}
}
重要:我必须使用Akka HTTP低级服务器API,所以我不能使用路由。
非常感谢您抽出宝贵时间提前提供帮助!
如果您只需要表单数据中的字符串值,您只需解组为 StrictForm
,然后将每个字段值解组为字符串。
这是一个概念验证 Ammonite 脚本,它使用 value1 & value2
:
import $ivy.`com.typesafe.akka::akka-actor:2.6.3`
import $ivy.`com.typesafe.akka::akka-stream:2.6.3`
import $ivy.`com.typesafe.akka::akka-http:10.1.11`
import scala.concurrent.Future
import akka.actor.ActorSystem
import akka.stream.scaladsl.Flow
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.common.StrictForm
implicit val system = ActorSystem()
implicit val ec = system.dispatcher
val requestHandler: Flow[HttpRequest, HttpResponse, _] = Flow[HttpRequest].mapAsync(1) {
case HttpRequest(HttpMethods.POST, Uri.Path("/api"), _, entity, _) =>
for {
strictForm <- Unmarshal(entity).to[StrictForm]
fieldsSeq <- Future.traverse(strictForm.fields) {
case (n, v) => Unmarshal(v).to[String].map(n -> _)
}
fields = fieldsSeq.toMap
response = fields("field1") + " & " + fields("field2")
} yield HttpResponse(StatusCodes.OK, entity = response)
}
Http().bindAndHandle(requestHandler, "localhost", 8080)